Wiley, Programming For The Series 60 Platform and Symbian Os (2003)
Wiley, Programming For The Series 60 Platform and Symbian Os (2003)
Copyright 2003 by Digital Information Architects Inc., (DIGIA Inc.) Published by John Wiley & Sons Ltd, The Atrium, Southern Gate, Chichester, West Sussex PO19 8SQ, England National 01243 779777 International (+44) 1243 779777 e-mail (for orders and customer service enquiries): [email protected] Visit our Home Page on http://www.wileyeurope.com or http://www.wiley.com 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, scanning or otherwise, except under the terms of the Copyright, Designs and Patents Act 1988 or under the terms of a licence issued by the Copyright Licensing Agency Ltd, 90 Tottenham Court Road, London UK, W1P 0LP, without the permission in writing of the publisher with the exception of any material supplied specically for the purpose of being entered and executed on a computer system for exclusive use by the purchaser of the publication. Neither the authors nor John Wiley & Sons Ltd accept any responsibility or liability for loss or damage occasioned to any person or property through using the material, instructions, methods or ideas contained herein, or acting or refraining from acting as a result of such use. The authors and publisher expressly disclaim all implied warranties, including merchantability of tness for any particular purpose. There will be no duty on the authors or publisher to correct any errors or defects in the software. Wiley also publishes its books in a variety of electronic formats. Some content that appears in print may not be available in electronic books.
Contents
Foreword by Nokia Foreword by Digia Authors Acknowledgements xv xvii xix xxiv
1
3 6 6 7 9 10 11 12 14 15 16 17 18
1.3 1.4
19
21
21 24 26 27 27 28
2.2
vi
CONTENTS
2.3 2.4
Browsing Example of Using Communications Technologies in the Delivery of Multimedia Messages Applications Summary
2.2.3 2.2.4
31 31 33 33
35
35 37 37 38 41 42 43 44 45 45 47 47 50
3.3
3.4
51
52 52 54 54 55 60 60 60 62 65 67 68 68 69 69 69 70
4.5
Platform Architecture
5.1 System Structure 5.1.1 Processes and Threads
71
71 78
CONTENTS
vii
5.2
5.3 5.4
EUser: Services for Applications 5.2.1 Memory Management 5.2.2 Exceptions 5.2.3 Descriptors 5.2.4 Multi-tasking with Active Objects 5.2.5 ClientServer Framework RockPaperScissors Engine Functionality Summary
79 80 83 84 87 89 90 92
93
94 94 94 95 96 97 98 99 100 101 101 102 105 105 108 109 113 113 114 115 115 116 116 117 118 121 121 123
6.2
6.3
6.4
6.5
6.6
viii
CONTENTS
6.7
Paper Prototyping or User Interface Simulation Tests 6.6.4 Lead Adapter Test Summary
6.6.3
Testing Software
7.1 Validation and Verication in Testing 7.1.1 Planning and Designing Tests 7.1.2 Entry and Exit Criteria 7.1.3 Failure Corrections Sources of Failures 7.2.1 Architectural Problems 7.2.2 Boundary Values 7.2.3 Combinations 7.2.4 Memory Management 7.2.5 Recovery Functions and Fault Tolerance Testing and Debugging Tools 7.3.1 Test Automation 7.3.2 Capture and Playback 7.3.3 Comparison 7.3.4 Debugger 7.3.5 Debug Output 7.3.6 Test Applications 7.3.7 Console Programs Unit Testing 7.4.1 Unit Testing Framework 7.4.2 Macros 7.4.3 Test Suite 7.4.4 Executable Test Cases 7.4.5 Test Execution Results 7.4.6 Summary of the Unit Testing Application Tester 7.5.1 DLL Command 7.5.2 Scripting Language 7.5.3 Summary of Digia AppTest Summary
131
132 133 135 135 136 136 136 137 138 139 140 141 142 142 142 143 143 144 144 146 147 147 149 151 153 154 155 156 160 161
7.2
7.3
7.4
7.5
7.6
163
165
165 168 173
CONTENTS
ix
8.2 8.3
8.4
Launching an Application Implementation of the User Interface of the RockPaperScissors Game 8.3.1 Creating the User Interface 8.3.2 Graphics Drawing and Event Handling Summary
194
194 196 197 198 203 204 205 206 206 206 207 209 209
9.2
9.3 9.4
212
212 214 214 214 214 215 215 216 217 222 224 225 227 228 230 236 241
239
239 241 242
CONTENTS
11.4
11.5
11.6
11.7
11.3.1 Editor Cases 11.3.2 Numeric Keymap 11.3.3 Input Modes 11.3.4 Special Character Table 11.3.5 Flags Notications 11.4.1 Conrmation Notes 11.4.2 Information Notes 11.4.3 Warning Notes 11.4.4 Error Notes 11.4.5 Permanent Notes 11.4.6 Wait and Progress Notes 11.4.7 Soft Notications Queries 11.5.1 Local Queries 11.5.2 Global Queries Setting Views 11.6.1 Setting Item List 11.6.2 Setting Items 11.6.3 Setting Pages 11.6.4 Custom Setting Page Summary
242 243 244 244 244 245 245 247 248 248 249 250 254 254 255 264 265 265 267 267 271 271
12 View Architecture
12.1 View Deployment 12.1.1 Views and User Interface Controls 12.1.2 Implementing View Transitions 12.2 View Runtime Behavior 12.2.1 Activation and Deactivation 12.2.2 Exception Handling 12.3 Summary
272
272 272 274 277 277 277 278
13 Audio
13.1 Playing 13.1.1 Priorities 13.1.2 Sinewave Tones 13.1.3 Audio Clips 13.1.4 Streaming 13.2 Recording 13.3 Summary
279
279 281 281 283 285 288 291
292
294 295 296
CONTENTS
xi
14.1.3 Status Pane 14.1.4 Notiers 14.2 Base Porting 14.3 Porting Applications to the Series 60 Platform 14.3.1 Functional Changes 14.3.2 Changes in the User Interface 14.3.3 Changes to Communications 14.4 Summary
307
309
309 310 313 319 319 321 322 323 324 326 327 327 327 329 331 331 332 333 333 334 334 335 335 335 336 337 338 340 341
xii
CONTENTS
342
343 343 349 350 351 351 351 354 356 371 371 373 374
17 Messaging
17.1 Messaging Architecture 17.2 E-mail 17.2.1 Sending E-mail 17.2.2 Receiving E-mail 17.3 SMS 17.3.1 Creating and Sending Short Messages 17.3.2 Receiving Short Messages 17.4 MMS 17.4.1 MMS Protocol Data Unit Structure 17.5 Smart Messaging 17.5.1 Bio Information File 17.5.2 Dening the Message Data Format 17.5.3 Implementing the SMS Viewer Plug-in Component 17.6 SendUI 17.7 Summary
375
375 382 383 385 386 387 390 391 392 395 396 397 398 401 405
18 Connectivity
18.1 Symbian Connect 18.1.1 Symbian Connect Features 18.1.2 Connectivity Architecture 18.2 Synchronization 18.2.1 Business Cards, Calendar Entries, and Mail 18.2.2 Synchronization Engine 18.3 SyncML 18.3.1 Device Management 18.4 Summary
406
407 407 410 415 416 417 418 421 422
CONTENTS
xiii
423
425
425 428 428 428 430 430 435 439 439 441 444 447
449
449 451 451 453 454 456 457 458 460 463 464 464 465 469 470 473 473 473 474 475 475 476 477 477 485 485 485 485
xiv
CONTENTS
20.4 Over-the-Air Provisioning 20.4.1 Over-the-Air Provisioning in the Series 60 Platform 20.5 Summary
490
490 490 492 492 492
Foreword by Nokia
Every day, millions of people around the world manage their mobile telephone communications with Nokia phones, without giving a second thought to the software inside their phones. This is not only a sign of good hardware design but also a sign of great user interface software and menu system design, often considered as one of the key success factors in Nokias mobile phones. For xed communications people are used to browsing the Internet, sending and receiving email messages, or creating documents on their personal computers. Although smartphones are not intended to replicate the functionality of personal computers they introduce true mobility and always-on data connectivity to people who want to have access to normally desktop-bound resources anywhere they go. How, then, is it possible to design highly functional yet simple-touse smartphone software that combines both voice communications and data connectivity applications? Early on, our user interface software design team concluded what the key factors for a successful smartphone were. It had to be as easy to use as a mobile phone. It had to integrate voice communication and mobile capabilities of a phone and key applications, such as multimedia messaging, scheduling, and browsing, into an attractive product package. We believe that years of experience with mobile phones, user interface development, and listening to our customers have paid off in the Series 60 Platform. The Series 60 Platform is a mobile terminal software platform built on Symbian OS. The goal was to design an open, standards-based platform for one-hand operated smartphones with color screen and keypad that features an intuitive user interface and key applications. Symbian OS was selected because it has been designed from the beginning for mobile phones and provides a stable platform with low power consumption and advanced memory management for a wide range of mobile phones, applications, and services. It is no coincidence that, besides Nokia, all major manufacturers in the mobile phone industry have invested in Symbian. Technical capabilities are important, but the attainable market size is crucial when considering a platform for application development. The rst product built on the Series 60 Platform available in shops was
xvi
FOREWORD BY NOKIA
the Nokia 7650. Siemens IC Mobile and Matsushita Communication were the rst companies that licensed Series 60 for integrating it in their own phones. These companies are also contributing to the future development of the platform, thereby demonstrating how the open, standardsbased product concept works for the benet of the entire emerging smartphone market. Software developers, operators, and IT vendors can rely on this platform, which is both shared and supported by the industry. Forum Nokia welcomes you to the world of smartphones and to the world of Series 60 software. It is great to see you join the pioneers of mobile application developers! Jouko H ayrynen Vice President, Forum Nokia Nokia Plc.
Foreword by Digia
In the mobile industry there are a number of factors linked to the success of smartphones starting with the hardware architecture and ending up with the applications. When a service or an application is installed on a smartphone, it must provide a positive and optimized user experience. Cross-platform standards, interoperability, captivating applications, high bandwidth networks, the robust Symbian OS, and suitable multimedia middleware are the platforms on which the next generation smartphones able to meet their full potential, leading to excellent consumer acceptance and market growth. As the market moves from simple voice devices to complex voice and data devices, new technology and new concepts in mobile software, such as the Series 60 Platform, are being introduced. Together with its customers and partners, Digia Inc. is playing its part in building a standard environment for interoperable smartphones. Digia Inc. has developed its strategy to contribute to market growth. The company is a global Finnish mobile software supplier of Personal Communications Technologies and Solutions for smartphones, and has been cooperating with Nokia on Series 60 Platform development for several years. Digia will offer the required integration and customization services to any licensee of the Series 60 Platform. Digia has proven its capability by developing major parts of Symbian OS phone projects, helping to reduce the time-to-market span signicantly for these new phones. Digia technology expertise and consultancy cover Symbian OS phone architecture from base porting to user interface customization, helping its customers to create, optimize, and differentiate their products. This book is a landmark for the Symbian economy in wrapping Digias expertise in the chapters of a single book. I would like to show my gratitude to Digia customers and business partners who have
xviii
FOREWORD BY DIGIA
contributed in the making of this excellent book. A sincere thank you goes to everybody at Digia who has put their expertise in the chapters, thus making this book possible. Jari Mielonen Chief Executive Ofcer Digia Inc.
xx
cumulative experience in designing and implementing Symbian OS software for several successful products at Nokia, Symbian, and Digia, where he is currently employed as a software specialist. His areas of expertise include designing user interface frameworks and designing application software and system-level components. Patrik Granholm has been working on numerous Symbian OS projects at Digia since the beginning of 2000. In his current position as a team manager, Patrik is responsible for a messaging competence team. Previously, he has worked on developing object-oriented systems, such as accounting software for Emce Solution Partner Ltd. Juuso Huttunen has experience in various software development tasks, from implementation to architectural design. He has gained both C++ and Java development experience in Symbian OS through several demanding projects. Currently, he is working in Digias Lappeenranta ofce, as a software engineer in the Java competence team. Ville K arkk ainen has an MSc in computer science, graduating from the University of Helsinki. In Digia, his current position is as a team manager. Ville is responsible for the competence development of the Communications and IP team in Digias Helsinki ofce. He is also working as a project manager in a large project, concerning a Series 60 smartphone. Matti Kilponen is a bachelor of visual and media arts, graduating from Lahti Polytechnic, Institute of Design. He has several years of design experience in multimedia and user interaction, and his current position in Digia is as an interaction designer. His previous career includes positions as a project manager and information designer at Razorsh, specializing in mobile content. His user-centered design expertise in Digia covers the Nokia Series 60 user interface style application design, user interface specication writing, interaction design, and early design verication. He specializes in the interface design of applications for the Nokia Series 60 Platform. Timo Kinnunen has an MSc (Eng.) in industrial engineering and management, graduating from the University of Oulu, Finland. He has several years experience in interaction design for mobile phone user interfaces. Timos current position in Digia is as a senior interaction designer in which he leads Digias User Experience Group. His previous career includes user interface and concept designing in Nokia. Timo has also authored scientic articles on concept design and has contributed to a number of pending patents on user interaction. His user-centered design expertise covers user needs research,
xxi
concept design, interaction design, and usability engineering, focusing especially on the Symbian OS user interfaces, such as Nokia Communicator, Nokia Series 60, and UIQ. Tomi Koskinen has a BSc (Eng.), graduating from Lahti Polytechnic Institute. He has been involved with Symbian OS in large-scale Series 60 projects, for over three years. During this time he has accumulated a thorough understanding of the platform and the available user interface components. Mika Matela has an MSc (Eng.) in information technology, graduating from the University of Lappeenranta. Currently, he is working at Digia as a software engineer. Previously, he worked as a designer at Kone Co. in Hyvink aa R&D center. Mika is experienced in various areas of product creation and, most recently, he has been involved in developing messaging solutions in Symbian OS. Ilkka Otsala is a student at Helsinki Polytechnic, where he is studying for a bachelors degree in software engineering. Ilkkas current position in Digia is as a software engineer. Previously, he worked at Nokia, where his main area of responsibility was user interface software. During his employment at Digia, Ilkka has gained a more thorough understanding of user interface software engineering on Symbian OS, especially the Series 60 Platform. Antti Partanen has an MSc (Eng.) in computer engineering, graduating from the University of Oulu. His current position in Digia is as a software specialist. Anttis previous positions include working as a software design engineer in Nexim Ltd, as a researcher at the University of Oulu, and as a software engineer in Tellabs Inc. He has experience and a thorough knowledge of many areas of Symbian OS. His main areas of expertise are communication protocols, system and communication architecture, and embedded systems. Timo Puronen has worked at Digia for over two years, and currently his position is as a software specialist. He has been involved in designing and developing messaging and communications software for the Series 60 Platform. He has studied at the Department of Computer Science at the University of Helsinki, and he is currently preparing his masters thesis on utilizing reusable software component frameworks in Symbian OS system software. Jere Sepp al a has a BSc (Eng.) from the Department of Telecommunication Technology, graduating from the Swedish Institute of Technology. He is currently a technology manager responsible for competence
xxii
development at Digias Helsinki ofce. He was previously a project manager at Digia and responsible for large software projects concerning a Series 60 smartphone. Before his career at Digia, he was employed by Ericsson. Where, he was involved in software production, for ve years, within different network standards, such as GSM, PDC, PCS, GPRS, and WCDMA. Juha Siivola has an MSc (Eng.) in computer science, from Lappeenranta University of Technology. In 1994, Juha joined Nokia and worked as part of the team that pioneered the rst revolutionary smartphone: Nokia Communicator 9000. As connectivity and interoperability became more and more important in mobile phones, he focused on the management of connectivity and subcontracting for the Nokia 9110 product. In February 1999, Juha joined Symbian, where he contributed to the denition of the Symbian Connect 6.0 release, later used in the Nokia 9210. In February 2001 he moved back to Finland and joined Digia where he works as head of product and technology management. Saiki Tanabe has a BSc (Eng.) in software engineering, from Helsinki Polytechnic Institute. The objective of his graduate study was to analyze how to initialize an Intel processor in an object-oriented operating system (Symbian OS). He has been working at Digia for two years as a software engineer, designing and implementing application programs for Symbian OS. His main area of expertise is system level user interface design, and he belongs to the user interface competence team at Digias Helsinki ofce. Jukka Tarhonen has worked at Digia in several positions, and his current position is as a team manager. Jukka is responsible for the Java competence team in Digias Lappeenranta ofce. His has a thorough knowledge of Java in Symbian phones as well as of Symbian implementation of the K virtual machine (KVM). His key expertise includes developing extension APIs for KVM (i.e. device-specic Java MIDP extensions in the Series 60 Platform). Tommi Ter asvirta has worked at Digia since early 2000. He has several years experience in training, consulting, and development with Symbian OS, starting from EPOC Release 3. As the training manager, he is responsible for all Digias Symbian OS related training. His duties also include technical consultancy in various software projects. He has lectured and delivered technical training sessions for hundreds of current and future Symbian OS professionals. Tuukka Turunen has an MSc (Eng.) in computer engineering from the University of Oulu and is a licentiate of technology in embedded
xxiii
systems, also from the University of Oulu. His current position at Digia is as a program manager. Tuukkas previous career included working as an R&D manager responsible for all product development projects in Nexim Ltd, as a senior assistant in computer engineering at the University of Oulu, and as a software engineer at Nokia. He has authored over a dozen scientic publications and conference presentations in the areas of communication protocols and virtual reality, as well as having contributed to several technical magazines. His main areas of technical expertise are communication protocols and embedded systems, and recently he has become increasingly interested in user experience design. Tommi V alim aki holds a BSc (Eng.) from Helsinki Polytechnic, Stadia (graduating in 1992, at which time the school was called Helsinki Technology School). Tommis area of specialization was telecommunications engineering, and his graduating thesis was on microprocessors real time operating system. Tommi joined Nokia in 1993 and started his current career in Digia in the beginning of 2000. He has several years experience in software testing, development, training, and research. His current position within Digia is as a senior testing engineer for Symbian OS and Series 60 environment.
Acknowledgements
This is the rst book ever written by Digia, and it was quite an experience for all the people involved. Despite the fact that we had lengthy experience in writing the technical documentation as part of the Symbian OS and Series 60 Platform software development projects, this book taught us that book writing is something else. The idea of the book came up within Digia at the end of 2001, as we saw a need to make life just a bit easier for the thousands of developers eager to learn more about programming for this exciting platform. It has been an honor for us to put a fraction of our knowledge and experience on paper and share it with readers. Being a professional software company, we could not gure out a better way of managing the writing of this book than establishing a project with a project manager, team, and steering group and creating detailed time, resource, and budget estimates. Our admiration of people who have written a whole book increased tremendously during the project. Also, having a large number of people involved in the creation of the book made the project management even more challenging. We hope that readers appreciate the extra insight that comes from the fact that the various chapters have been written by experts in those areas. This was a true team effort and the result of many people working closely together. The authors volunteered to do the writing, which in practice meant that many of them ended up spending their evenings, nights, and weekends working on this book. We would like to take this opportunity to thank all who contributed to the book and supported us during the project. If this book is useful to you, remember that these people had a great deal to do with that. First of all, we would like to express our gratitude to the numerous people at Nokia and Symbian with whom we have worked throughout the past years. Without the support and input from both Nokia and Symbian, writing this book would not have been possible. Thanks for trusting us and giving the opportunity to work in this exciting area. From the publisher John Wiley & Sons, we would especially like to thank our publishing editor Karen Mosman, for the lessons learned and for the valuable pieces of advice on how books should be
xxvi
ACKNOWLEDGEMENTS
written thanks for your patience and good cooperation! Thanks to Jo Gorski for her efforts in promoting the book, and Geoff Farrell for making this book available for corporate buyers. Additionally, big thanks goes to the rest of the team at John Wiley & Sons, including the copy editors, artists, and production people who worked hard on this project. Several people outside Digia have reviewed and commented the manuscript, and with their comments the outcome has been signicantly improved. We are very grateful to all the individuals who have commented either parts of or the entire content of the draft of the book. Special thanks are due to external reviewers Robert van der Pool and Vladimir Minenko from Siemens, Sudeesh Pingili and Richard Baker from Panasonic, John Roe from Symbian, Rob Charlton from Intuwave, as well as Olli Koskinen, Matti Kakkori, and Mika Muurinen from Nokia, for their thorough and detailed review. If you have ever technically reviewed a proof copy, you know how much work this is. These people went an extra mile and obviously read in their own time, and for this we thank them profusely. We would also like to thank all the people who made the book more enjoyable to read. Among them are Marketta R aih al a, who made the English more understandable, Martti Lepisto, who improved the graphical representation of the images in the book, and Ville Koli, who did the cover design of the book. Several of Digias professionals have contributed as authors to the writing of this book, and even more have helped by giving ideas, reviewing, supporting, and commenting. Especially helpful comments in the formal review were received from: Jari Hakulinen, Jani Harju, Tuomas Harju, Kari Hautam aki, Kimmo Hoikka, Eeva Kangas, Ossi Kauranen, Jari Kiuru, Henri Lauronen, Petri Lehmus, Markku Luukkainen, Pasi Meri, Tomi Meri, Ville Nore, Jari Penttinen, Heikki Pora, Sami Rosendahl, and Tapio Viitanen. The source code examples were reviewed by Kimmo Hoikka and Petri Poikolainen, for which the authors wish to acknowledge them. Special thanks are also due to Pekka Leinonen for organizing the formal reviews to all the chapters, and to Tino Pyssysalo who, in addition of being the principal author, was the project manager of the book creation project. Tino did an outstanding job of managing and coordinating all the various pieces of the project. The rest of us really appreciate all your efforts! The authors wish to acknowledge all the members of the steering group of this project: Minna Falck, Jari Kiuru, Pekka Leinonen, Inka Luotola, Tino Pyssysalo, Juha Siivola, and Tuukka Turunen, as well as the Digia management team and all our other colleagues for all their support and efforts that made this book possible.
ACKNOWLEDGEMENTS
xxvii
On the personal side of things, we want to thank our families and friends. Thanks for understanding and thanks for being there. And nally, we would like to express our gratitude to all the other people who are not listed here by name but who helped us in running the marathon this book presented: THANK YOU!
1
Introduction to the Series 60 Platform
The market drive towards advanced mobile services such as multimedia messaging and wireless access to the Internet sets high requirements for the terminals and networks. New devices (and networks) must be able to handle still and moving images, music, allow access to the Internet for messaging and browsing, and provide a diverse set of applications in addition to operating as a mobile phone. As 2.5G and 3G networks emerge, the focus is turned to the terminal what kind of capabilities are required by these new services and how can they be fullled? This book presents one signicant platform for smartphones devices that are designed to meet the increasing requirements of the new services Series 60. It is a platform made by Nokia on Symbian OS (Operating System), which in turn is an operating system designed for mobile devices. Owing to these requirements of the new services, the task of making the software for wireless devices is becoming increasingly complex. As new protocols, communication interfaces, services, and applications are integrated, the required R&D effort grows rapidly. This increases the development cost signicantly and sets high demands on interoperability testing. Symbian was formed in 1998 by Ericsson, Motorola, Nokia, and Psion to provide a common standard and to enable the mass marketing of a new era of wireless devices. Matsushita (better known by its brand name, Panasonic) joined Symbian in 1999, in January 2002 the Sony Ericsson joint venture took a share of Symbian, and, in April 2002, Siemens also joined Symbian as a shareholder (www.symbian.com). The cost of the hardware components (i.e. bill of materials) used for making a mobile phone is one of the most important factors in making competitive devices, but the cost of developing and maintaining the increasing number of features of the software also becomes more signicant as the world evolves towards wireless multimedia. When the mobile phone shipping volumes are low, the price of the hardware
components, especially the most expensive ones, such as the color display, is high. When components are made in high volumes, the price of a single component is reduced. New requirements are set for the operating system by the need to open the devices for developing thirdparty applications in order to have a more diverse set of applications to attract more users and to increase volumes. A typical smartphone is attractive for users looking for more features compared with the basic mobile phone. Also, for those seeking better personalization, a smartphone is likely to be a natural choice. A smartphone is, as its name states, a phone, but with capabilities such as color screen, advanced messaging, calendar, browser, e-mail, synchronization with other devices, and, installation of applications. From the device manufacturer perspective, it is vital that the software is stable and reliable especially if it is possible for the user to install new applications. A serious software or hardware defect may force a manufacturer to call back all the mobile devices. The costs of such an operation are very signicant even when compared with development costs. From the software point of view, the right selection of software platform will reduce the risk of failure. Series 60 Platform is particularly appealing for the terminal manufacturers, as it allows Symbian OS with multimedia capabilities to be used in devices that are only slightly more expensive than the devices equipped with a proprietary operating system. Series 60 Platform provides the benet of open interfaces, efcient power management, and advanced multimedia capabilities. From the application developer perspective, Series 60 is also very interesting, as the compact size and reasonable price of the devices leads to large market penetration, thus making the application development worthwhile as well. This book is written by the software professionals of Digia a company that has been heavily involved with Symbian OS and Series 60 Platform and application development since early 1999. During that time, knowledge of the platform has been accumulated in demanding, time-critical projects and in developing products for Symbian OS. This book is a handbook of software development for the Series 60 Platform, written by software professionals for software professionals and for individuals who want to become experts on Series 60 software development. The approach of this book is to build on top of the previous publications on Symbian OS and to provide a guide for the art of developing software for the Series 60 Platform. The intended audience is anyone interested in learning more about Symbian OS and the Series 60 Platform. It is specially benecial for software developers who can use the code examples for illustrating the key aspects of Series 60 software development.
1.1
Figure 1.1 Examples of smartphones: a smartphone looks like a normal cellular phone and typically provides a color screen capable of displaying graphics and several value-adding applications
In addition to features easily noticed by the user, there are other types of requirements for smartphones. As they are embedded systems (like all mobile phones), behavior accepted for typical personal computers cannot be tolerated. The operating system of the smartphone needs to be very reliable and stable system crashing and rebooting are most undesired features. It must also t into a very small amount of memory and use the resources sparingly. A real-time nature with
predetermined response times is required of the parts that deal with the cellular networks, and it is preferred that the entire system provides fast response times. The overall quality of the operating system and the software platform of the smartphone needs to be very good, as the cost of replacing the software with a new version is high. Smartphones are devices that are always on and typically run for weeks or months without restarting. Actually, many users turn their devices off only when traveling by plane in all other situations the silent mode is sufcient. Another issue is the nature of data and storage media used with these devices. As the users store important personal data such as their itineraries and precious memories loss of data simply cannot be tolerated. These set stringent requirements for the memory management in the smartphones, and a smartphone operating system must be robust and support design principles that allow other software to be reliable. Robustness of the operating system is one of the key criteria to be considered when selecting the platform for smartphones. Especially important is the performance in error conditions, and it is vital that the user data and system integrity are not compromised in any situation. Key requirements for hardware components are a small form factor, high tolerance of abuse, and extremely low power consumption (and low manufacturing and integration costs). The power consumption is particularly vital, as the amount of energy needed is stored in the battery, and most users do not want to charge their devices daily. In addition to selecting hardware components suitable for achieving low power consumption, the software has to operate in such a way that energy is conserved to the extent possible in all situations while providing the response times and performance needed by the user or the network. The operating system of a smartphone is the most critical software component as it depicts the nature of software development and operating principles. The most important requirements are multi-tasking (with multi-threading), real-time operation of the cellular software, effective power management, small size of the operating system itself, as well as the applications built on it, ease of developing new functionality, reusability, modularity, connectivity (i.e. interoperation with other devices and external data storage), and robustness. Based on the choices of the worlds top mobile phone manufacturers with the largest market share (Nokia, Motorola, Samsung, Sony Ericsson and Siemens holding almost 80% of the market), the most signicant alternatives for extending smartphone functionality in a phone are either Symbian OS or the manufacturers proprietary operating system. Although it is possible to select some of the operating
systems used in personal digital assistants, such as Palm OS and Pocket PC (or its smartphone variant called Smartphone 2002) or to take an open-source approach with Linux, these solutions tend to raise problems, such as lack of power, excessive build cost, and fragmentation. The hardware platform especially the selected processor architecture inuences the suitability of the different operating systems for the device. For example, Symbian OS is currently used mainly with the ARM architecture and instruction set. However, it is possible to use Symbian OS with virtually any hardware platform by tting the operating system to the new platform (called base porting). It also means that for the same type of hardware actually, even for exactly the same hardware it is possible to t many of these smartphone operating systems. In practice, the cost related to creating and supporting the smartphone software (and also the fact that third-party applications would then be incompatible) makes an industry-standard operating system a more practical approach. Power management is a usability issue to some extent. Although it is very important to use effective power-saving modes whenever possible, it cannot happen at the users expense. This means that the response times need to be short even when the system is in sleep mode. Reaction to, for example, the user pressing a button, or the network signaling an incoming call, has to be immediate. Also, the boot sequence needs to be short and preferably allow user interaction even when some services are not yet invoked. A typical design choice supporting modularity and allowing the robustness needed in consumer devices is the microkernel approach. Only very little code (the microkernel) runs in the privileged mode while other system components are built on top of it to provide a modular and extendable system. Additional benets of the microkernel approach are increased security and robustness. As only a small part of the operating system runs in privileged mode, the likelihood of errors causing total crashes is minimized. Generally, in software platforms the modularity and architecture dene the extendibility and lifecycle of the platform. In operating systems, the modular approach is most future-proof as it allows new functionality to be added in the form of additional modules and functionality to be removed that is no longer needed. Modularity can also benet memory consumption, as applications can rely on the same software components as do the system services, thus reducing the total memory consumption by resource reuse. Considering all the issues presented above, analyzing them against the cases presented for new smartphones and selecting the best
operating systems sounds like a straightforward task for the terminal manufacturer. In many ways it is, but additional challenges arise in providing the software that sits on top of the core operating system. Matters such as availability of standard communication protocols, the interoperability of the system, interfaces and tools allowing third-party software development, the capability to support common development and content creation methods, an attractive and customizable user interface allowing good usability, support, and, naturally, the cost need to be carefully balanced as well. This section has covered the requirements of a smartphone operating system from the perspective of the terminal manufacturer. In the next two sections, an approach answering the demands namely, Symbian OS and Series 60 Platform is presented. Although this section has looked at the choices of creating smartphones from the viewpoint of the device manufacturer, the aspects covered affect the application developers as well. Comparison of different operating system choices has been kept to a minimum in order to give a general view on the topic.
1.2 Symbian OS
Symbian was formed from Psion Software by Nokia, Motorola, Psion, and Ericsson in June 1998. In 1999 Matsushita (Panasonic) and in April 2002 Siemens joined Symbian as shareholders. From the very beginning, the goal of Symbian was to develop an operating system and software platform for advanced, data-enabled mobile phones. For this purpose, the EPOC operating system developed by Psion formed a solid foundation. It was a modular 32-bit multi-tasking operating system designed for mobile devices.
SYMBIAN OS
developing the communication protocols, user interfaces, and other parts of the system. The modular microkernel-based architecture of the EPOC operating system allowed this and, after EPOC release 5 (last version, used mainly in Psion 5), the operating system was renamed Symbian OS. Symbian is a joint venture between leading mobile phone manufacturers formed to develop a common operating system suitable for mobile communication devices. The operating principle is quite simple: Symbian develops and licenses Symbian OS containing the base (microkernel and device drivers), middleware (system servers, such as the window server), a large set of communications protocols, and a test user interface for the application engines of the operating system. Licensees develop the user interfaces to suit their purposes, and they also have the ability to license their user interface and application set on top of Symbian OS to other Symbian licensees as Nokia has done with Series 60. The terms of licensing Symbian OS are equal, and there are (at the time of writing) 10 licensees in the list, containing (in addition to the owners Ericsson, Matsushita, Motorola, Nokia, Psion, Siemens, and Sony Ericsson) companies such as Fujitsu, Kenwood, and Sanyo. Symbian develops new versions of the operating system, but the licensees can make their own alterations to the look and feel of the system, to the applications, and to the development tools. This is important in order for the licensees to be able to adapt their devices to their brand and also to have a variety of different types of devices to address different market segments. For the developer community, Symbian offers technical support and guidelines for developing software. This is particularly helpful to the smaller licensees who do not have the resources to set up their own developer network and support areas. Symbian provides training directly and through its training partners. For the licensees, Symbian offers support via its Professional Services department, and more support and work on a pay-per-service basis is available from the Symbian Competence Centers companies specialized in helping the Symbian licensees in developing their terminals.
1.2.2
When two devices have different user interface libraries providing an entirely different look and feel they still contain the common code from Symbian OS. This provides interoperability, simplifying developing applications for several different devices and decreasing the costs of making different kind of devices. In this section, the principles of Symbian OS architecture are covered to provide grounds for understanding the concepts. Different user-interface styles are also presented. The structure of Symbian OS v6.1 for Series 60 Platform is shown in Figure 1.2.
Application engines Phone book, calendar, photo album, notepad, to-do, pinboard Installed applications Games, self-developed applications, utility software Messaging SMS, MMS, e-mail, fax MIDP Java KVM
Application framework GUI framework (Avkon, standard Eikon, Uikon), application launching, and graphics Multimedia Images, sounds, graphics Security Cryptography, software
Communications infrastructure TCP/IP stack, HTTP, WAP stack Telephony HSCSD, GPRS Base User library, kernel, device drivers
Legend: GPRS GUI HSCSD HTTP KVM MMS SMS TCP/IP WAP General Packet Radio Service Graphical User Interface High Speed Circuit Switched Data Hyper Text Transfer Protocol K Virtual Machine Multimedia Messaging Service Short Message Service Transmission Control Protocol / Internet Protocol Wireless Application Protocol
Figure 1.2 Structure of Symbian OS v6.1 for Series 60 Platform; for abbreviations, see the Glossary
Symbian continuously develops Symbian OS to contain the protocols and features most needed by the licensees. The rst Symbianreleased software was Symbian OS v5, a unicode version of EPOC Release 5.0 from Psion. Symbian OS v5 was used in one family of smartphones the Ericsson R380 series (R380s, R380e, R380 World). The rst actual open platform release was Symbian OS v6.0 in spring 2000, used in Nokias 9210, 9210c, 9290, and 9210i Communicators. Symbian OS v6.1 was shipped January 2001 and is used as a base technology for the Series 60 Platform (e.g. in the Nokia 7650 and 3650 imaging phones). Symbian OS v7.0 was released in spring 2002 and is common to several upcoming devices, such as Sony Ericsson P800.
SYMBIAN OS
As new versions of Symbian OS become available it is possible for the licensees to develop new product on top of these. The development lifecycle for a new mobile communication product typically lasts 23 years (depending on the amount of resources, experience, and the product in question). A variant of an existing product can be made signicantly faster (in even less than a year). It is not feasible to change the operating system used in a products each time a new version is developed. For example, the Nokia 7650 uses the Series 60 Platform built over Symbian OS v6.1. It is technically possible to change the version of the underlying Symbian OS to a new one. Whether it will be done depends on the benets gained with the new version compared with the costs of implementing the change. Unlike in the desktop computing world, a new version of the operating system is not tted into the existing hardware but into devices that are made after the release of the new operating system version.
1.2.3
Generic Technology
Most parts of the generic technology remain unchanged between different devices utilizing Symbian OS. The architecture of the system is modular, and it is designed with a good object-oriented approach. Most of the operation is based on a clientserver model to allow all applications to use the services provided by the system, as well as other applications. This provides a very exible system, allowing secure and robust resource allocation. It also saves signicantly in the binary size and development effort of the applications, as the most used functionality is provided by the platform. Generic technology also contains a security framework that provides certicate management and cryptography modules (Mery D., 2001). The base is the bottom layer of the operating system. It consists of the microkernel, device drivers, and user library. The microkernel is run directly in the processor in privileged mode. It is responsible for power management, memory management, and owns device drivers. The device drivers are the hardwaresoftware interface layer needed for accessing, for example, the display and audio devices of the terminal as well as the communication channels. The user library in turn provides many of the functionalities such as error handling, cleanup framework, hardware abstraction layer, clientserver architecture, as well as context (i.e. process and thread), and memory management, used by virtually all programs. Application framework in turn is a set of reusable libraries providing means for handling text, graphics, and sound. As smartphones are sold globally, it is vital that internationalization and localization are well supported in the Symbian OS. Internationalization (i.e. customization of applications, presentation, and content to support local
10
units, standards, practices, and traditions) is handled mainly by the application framework. Localization (i.e. translation of the text strings to different languages and character sets) is done separately for each application. One important part of the application framework is the window server, which also provides keyboard and pointer support (for devices with a touch screen). The graphics framework is part of the application framework and contains parts that are common to all terminals as well as parts that are specic to the user interface library or manufacturer (depending on the amount of customization performed). Communication architecture contains the infrastructure needed for communications and protocol stacks of the most needed communication protocols. One of the key strengths of Symbian OS is the provided set of communication methods and their tested interoperability. In addition to the protocols provided with the system, the licensee and the application developers are able to create support for additional protocols in the form of new protocol modules or by building the needed protocol into an application.
SYMBIAN OS
11
Symbian OS
Figure 1.3 Symbian OS: Series 80, UIQ, with its two widths, and Series 60 are currently the most important user interface styles
and 9210i communicators; Nokia has not made any announcements on licensing Series 80. The Sony Ericsson P800 in turn uses the slim version of UIQ, Nokia 7650 and 3650 use the Series 60 Platform. Each user interface style allows customization of the look and feel of the user interface for each licensee and device. When Nokia, for example, licenses Series 60 Platform to some other manufacturer, the user interface is likely to look somewhat different. This is natural, as the physical shape of the smartphone is different. Simple customization of the graphical user interface may consist of changing the shape and colors of the graphics (bitmaps), changing menu text and structure, and the addition of new components, e.g. applications. The purpose of customization is not only to tie the smartphone tighter to the licensee brand but also to make the device more usable for the intended user group.
1.2.5
Application Development
Symbian OS supports application development with C++ for building native applications and with Java for building Java applications and midlets (i.e. Java MIDP applications). C++ development is done with Symbians extensions and differs somewhat from, for example, C++ development for Microsoft Windows. The biggest difference from the development with standard C++ is the unique approach to exception handling, which was not supported by the compilers available in the early phase; it is also better suited to its purpose than is the generic approach. Development with Java can be somewhat easier than C++ programming language, and the developer community for Java is larger. The performance issues and available interfaces restrict Java development to certain types of applications. For these, the decision to develop with Java for Symbian OS is a sound choice. The development tools are available from tool partners, including Metroworks, Borland, and Appforge. Currently, Series 60 uses
12
Microsofts Visual Studio in the C++ Software Development Kit (SDK). The development is done on ordinary desktop computers, and the SDK provides good development support and allows applications to be tested without the target hardware (to some extent). With the development tools, the compilation for the target device can also be performed, and installation packets (Symbian Installation System SIS les) can be created. Although development with the SDK allows testing of the application to some extent, it is also important to install the application into the target device to test the operation fully. Testing the software in the target device requires a big effort as the tester needs to enter all the commands manually to test the functions of the software. It is especially time-consuming to perform tests several times (e.g. it takes a great amount of time to test memory allocation operation 10 000 consecutive times to see whether it always succeeds). There are tools available for automating the testing in the target device and for providing a better quality nal software. This type of tool signicantly reduces the effort needed for performing thorough tests. Some other important aspects of developing applications for the smartphone are interaction design, user experience, security, and localization for different languages. Usability and interaction design of software developed for smartphones is demanding, as the user interface is very small, allowing only the most important information to be included. Also, the possible user base is very diverse, and help les or user manuals should not be needed at all users of smartphones do not necessarily have experience with, for instance, computers. Security is provided by the operating system to some extent, but it is important not to compromise the system (in the sense of being vulnerable to attacks) through the developed applications installed by the user. Localization of the application for different languages including those with different character sets is supported quite well by Symbian OS. This is a very important feature, as developing a new smartphone is such an investment that in most cases it requires global sales in order to be protable. The platform is localizable for several countries (in terms of units, languages, and character set), and the third-party applications can also easily be translated to several different language versions.
13
Why should some device manufacturer license Series 60 Platform to use on top of Symbian OS, and why does Nokia want to license this platform to its erce competitors? The answer to the rst question is relatively easy, as Series 60 Platform and Symbian OS provide a user experience and application set unlike any other smartphone platform in a very competitive package. An example of the applications view and other screenshots of the Series 60 Platform are shown in Figure 1.4.
Figure 1.4 Nokias Series 60 Platform: screenshots; Series 60 Platform provides a graphical user interface and a large set of applications
It takes great effort from a mobile phone manufacturer to create a comparable user interface and application set even if they start building this on top of Symbian OS. Actually, this partially answers the second question to be able to make the developer base larger, and thus to create more content, Nokia wants to license its smartphone platform to all manufacturers. This in turn is important, as a large amount of available content and a large number of devices from different manufacturers lead to an increased number of users (and thus terminal volume), which reduces the cost of the components needed in the device. At the time of writing Siemens, Samsung, and Matsushita (Panasonic) have announced they are licensing the Series 60 Platform. In addition to Nokia, they are likely to be the rst device manufacturers to offer smartphones based on the Series 60 Platform. For a Series 60 licensee the platform forms a solid base for the much faster creation of smartphone devices than can be achieved by other approaches. In addition to accelerated time-to-market, competitive advantage is gained as the needed hardware components for building the smartphones are available at a reasonable price. The supported display resolution of 176 208 pixels allows the creation of reasonably priced smartphones. It is also easier to enter the smartphone market with Series 60 Platform as there is already an established developer base. Series 60 terminals are binary-compatible with each other; that
14
is, the application developed for Nokias Series 60 terminals are interoperable with other Series 60 terminals (with the exception of unsupported features, such as trying to take a picture with a device without a camera). The Series 60 Platform 1.0 (built on Symbian OS v6.1) provides the communication technologies needed in smartphones such as: e-mail (with POP3, IMAP4, SMTP), WAP 1.2.1 stack, SyncML 1.0.1, MMS, Bluetooth, GPRS, and, naturally, all the other necessary protocols supported by Symbian OS v6.1 (see Glossary for terms and abbreviations). The list of applications provided with the platform includes a phonebook, calendar, notepad, photo album, clock, calculator, composer (for creating ringing tones), e-mail client, SMS and MMS clients, as well as the telephone application. All these features are encapsulated into a well-designed graphical user interface with tested usability (Nokia, 2001c). It is possible to create a smartphone with just these reference applications, but the licensees are likely to add new features and applications (such as games) to the devices. Naturally, the new licensees are likely to customize the platform simply by creating different types of graphics and color schemes, but they may also use advanced techniques such as altering the default applications. For this purpose, the development is, naturally, done with C++. Application development in Java for Series 60 is done with the Mobile Information Device Prole (MIDP). This allows a certain degree of interoperability with MIDP applications, such as simple games that will run on any MIDP-enabled device, if the capabilities are suitable.
15
development. In addition, the essentials of Symbian OS programming and development support are included in these chapters. More experienced Symbian OS developers may jump directly to any part that seems to provide interesting information. It is recommended that chapters of each part are read in the given order, because each chapter builds at least partially on the previous chapter. Every part begins with an introductory chapter, which presents an overview of the topic. These opening chapters also give background information beyond the Series 60 Platform and are useful to anyone who wants to gain an overview of some technology supported in Symbian OS.
1.4.1
Contents of Part 1
The software engineering principles on the Series 60 Platform are walked through in Part 1. Chapter 2 gives a high-level overview of the platform, including the features of the user interface, supported communications technologies, and preinstalled applications. This chapter should be read by anyone who wants to know what the Series 60 Platform actually is and how it is related to Symbian OS. In the design of Symbian OS and user interface libraries provided by the Series 60 Platform, the same design patterns have frequently been applied. In Chapter 3, modelviewcontroller, observer, clientserver, adapter, microkernel, and state design patterns in addition to some idioms relating to memory management are described. Chapter 3 helps in understanding how design patterns have inuenced the application framework of the operating system and how these design patterns are applied in application development to make software components more robust, reusable, and portable. As an example, the most frequently used design patterns are applied in the design of a simple rockpaperscissors game. Chapters 4 and 5 are targeted mainly at programmers who have no earlier experience in Symbian OS. In these chapters, the software build process and the use of build tools are described. Development support can be found in the web links provided. Owing to the limited space we cannot describe all the details of Symbian OS, but we do describe the basics of memory management, exception handling, multi-tasking, clientserver framework, and descriptors to help the reader to understand the code examples given in the rest of the book. We use code fragments of the rockpaperscissors game designed in Chapter 3 to emphasize the characteristics of Series 60 Platform and Symbian OS programming. The quality of smartphones and applications is determined by their usability. That is why it is essential to take usability issues such as user interface and interaction design into account when designing
16
software for smartphones. Chapter 6 describes the user interaction design process, starting from user needs and ending with usability verication. By reading Chapter 6, developers will learn how to design their applications for usability. Part 1 ends with a chapter presenting software testing for smartphones (Chapter 7). The scarce memory resources, the robustness requirements of applications, and other special characteristics of smartphones increase the importance of ensuring good quality applications. Each software developer should know the testing techniques and strategies as well as the possibilities and limitations of the available testing tools.
17
between views in different applications. For example, a user may store received contact information in the messaging application by switching to a view of the phonebook application, without starting the phone application by hand. Chapter 12 describes how views are dened and used on the Series 60 Platform. Graphics is not the only part of the user interface; with respect to user experience, audio may be as important. Chapter 13 contains a description of how to use different audio formats to record and play back audio data on the Series 60 Platform. Again, we have included code examples to clarify the use of audio. By following the conventions and recommendations from Symbian, the porting of an application between user interface styles should require only the porting of the user interface part. Chapter 14 gives developer information on, how to customize the look and feel of user interface components and how to port the Series 60 Platform to new devices. Chapter 14 also includes a description of application porting from previous user interface styles to Series 60.
1.4.3
Contents of Part 3
Part 3 concentrates on networking and communications. Chapter 15 is an introductory chapter in which we describe supported communication techniques and also background to information to provide an understanding of how different protocols work and what kind of characteristics they have. An important part for all developers is the description of communications architecture of Symbian OS. This helps in understanding how to use any supported communications service. Chapter 16 gives examples, of how communications services, described in Chapter 15, are used in applications. The description follows the structure of the communications architecture, presented in Chapter 15. Use of programming interfaces of any of the Symbian OS communications servers (Serial communications server, Socket server, and Telephony server) is described, with code examples. An example of the use of these programming interfaces is how different communications technologies may be used to transfer the protocol messages of the rockpaperscissors game. Chapter 16 is useful to anyone who is going to use communications services in applications. Messaging is another way of communication and the subject of Chapter 17. The messaging architecture and messaging examples (with source code) using e-mail, short messages, multimedia messages, and smart messages are described. Connectivity issues related to le management, remote printing, and synchronization of data between the smartphone and other devices
18
are described in Chapter 18. In addition, SyncML language for data synchronization is described in this chapter.
Part 1
Software Engineering on the Series 60 Platform
2
Overview of the Series 60 Platform
The Series 60 Platform is designed for one-hand operated smartphones. It is based on Symbian OS and completes it with a graphical user interface (UI) library called Avkon. The Avkon library has been designed to enable the implementation of intuitive and easy-to-use applications. According to the design goals of the platform, using a smartphone should not be more difcult than using an ordinary mobile phone. In addition to the UI library, the platform contains a set of reference applications providing a public API (application programming interface) to the services of these applications. The reference applications help software developers to use a proper UI style. This chapter provides a more detailed overview of the Series 60 Platform than presented in the previous chapter. We describe the physical characteristics of the user interface, the set of built-in applications, and the supported communications technologies to give the reader an idea of the possibilities and limitations of the platform. The software examples are found in the following chapters, where the essential design patterns useful in application development are described.
2.1
User Interface
The user interface of the smartphone is one factor with which the device manufacturer may differentiate its products from those of other vendors. Differentiation is the key word for surviving and succeeding in the global mobile phone markets, and thus each device manufacturer intends to provide a unique and competitive user interface, satisfying customer needs. Licensees can customize the Series 60 Platform user interface according to their own look-and-feel requirements. However, all the programming interfaces to the third-party developer will be the same in all Series 60 phones. The platform supports a screen size of 176 (width) 208 (height) pixels by default. In future versions, the
22
vertical resolution should be modiable. Phones based on the platform should have a display supporting 4096 colors or more. There is no need for a pen or full keyboard, which enables phones to be used by one hand. However, it is possible also to use an external keyboard if the device manufacturer wants to build the required hardware support for it (Nokia, 2001g, pages 89). The Series 60 platform user interface is designed to make use of the smartphone as easy and intuitive as use of a mobile phone. At the highest level, the application user interfaces may be considered as consisting of two parts: browsing elements and detailed views. By browsing, users make selections (e.g. an entry from a list). After the selection, the corresponding detailed view of the entry displays the data on the screen. For data input, the platform species a 12-key ITU-T (International Telecommunication Union Telecommunication Standardization Sector) numeric keypad (09, #, *) with additional function keys. Function keys include two softkeys (left and right softkeys having a textual label on the bottom of the screen), ve-way navigation key (up, down, left, right, and select), an application launch-and-swap (application) key (bringing up the application shell), and send and end keys for call handling (Nokia, 2001c). An illustration of the keypad is shown in Figure 2.1.
Left softkey Application key Send key Right softkey Navigation key End key
The left softkey is typically labeled Options, because it is used to open the options menu. In other states, Select, OK, and Yes are used to select items in menus or lists and to give a positive reply to a conrmation query. The right softkey is used for returning to the previous state and thus is usually labeled Back. It is also used for exiting
USER INTERFACE
23
Figure 2.2
an application, canceling a procedure, or to give negative replies, in which cases the Exit, Cancel, and No labels are commonly used. Typical labels are shown in Figure 2.2. Software developers dene the labels in application resource les. The keypad also species a clear and an alpha toggle key for improving the text input. The alpha toggle or edit key is the only key that may be pressed down simultaneously with any of the navigation keys, in rare cases, for which both hands are required. One implementation of the Series 60 user interface is provided by Nokia 7650 phone, shown in Figure 2.3. Manufacturers can extend their products based on Series 60 to have other functional keys or even an external keyboard. Extra keys may be used to control the hardware or applications, for example in speech recognition or volume control.
24
Keys may allow interaction, when they are pressed down, held down, or released. Typically, the interaction occurs when the key is pressed down, but the behavior of the edit key is different, because it may be pressed simultaneously with other keys. Based on Nokias specication (Nokia, 2001g, pages 1819), a short key press lasts less than 0.8 seconds. A long key press may cause another interaction in addition to the key press, after a duration of 0.8 seconds. A long key press may also perform a key repeat, in which the same function associated with the key is repeated at a user-specied frequency.
2.1.1
Avkon
Standard Eikon
Uikon
Application architecture
Control environment
USER INTERFACE
25
Avkon-specic controls to be used in the applications. Controls are GUI components, displayed on the screen. Commonly used controls include menus, dialogs, notications, list boxes, conrmation queries, and edit windows. Menus are opened with the left softkey, labeled Options. The contents of the menu is context-specic and may be dynamically changed in the application. For example, a communication application may hide receive and transfer menu items, until the connection to the destination has been established. Menus may also contain submenus. For example, the user may choose to send a document to the receiver, using either Bluetooth, infrared or short message service (SMS), as shown in Figure 2.5.
Figure 2.5 Examples of user interface components: menu (left), a single list with icons (middle), and a dialog box (right)
Dialogs are pop-up windows that are used in numerous cases to query some information with the user. The information may be a password, le name, any editable text, time, date, telephone, and so on. A simple dialog may ask the user to conrm a procedure before execution, but more complicated dialogs contain several lines, each having a label and a control. The control may be an edit window allowing the user to edit the text in the dialog. Avkon notications replace information and query windows of the previous UI styles. Notes are dialogs that may disappear without user interaction. They are used to notify the user about exceptional situations, when running the software. List box is not a single UI component but contains a number of list and grid types. Lists contain items, which are browsed vertically, whereas grids are two-dimensional lists, allowing navigation in both the horizontal and the vertical direction. Lists may allow looping from the end of the list back to the beginning of the list. In addition, there are a single and double column, and single and multiple selection lists. A detailed description of the list types is given in Chapter 10; the rest of the UI components and examples of their usage are given in Chapter 11.
26
COMMUNICATIONS SUPPORT
27
communications technologies is supported. Connectivity allows shortrange connections between a smartphone and other devices to synchronize data or to transfer les. Short-range connections themselves enable multiparty data transfer or, more interestingly, multiplayer games. Cellular networks may be used for Internet access, messaging, and voice communications. Application designers, utilizing supported communications services, require standards for ensuring interoperability between any devices. The Series 60 Platform uses global protocol standards for communication. For instance, in remote connectivity purposes the Series 60 Platform introduces the SyncML protocol. The protocol is used for data synchronization between applications across multiple platforms and for standardized device management functions. However, in the rst release of the Series 60 Platform, device management is not yet supported. An example of data synchronization is the exchange of vCard and vCalendar objects between a smartphone and a desktop. SyncML also provides an alternative for proprietary device management implementations, which may be difcult to use by the end-user. The protocol allows the use of several protocol bindings in the exchange of synchronization or management data. Three bindings are supported in Symbian OS: HTTP (hyper text transfer protocol), WSP [wireless application protocol (WAP) Session Protocol], and OBEX (object exchange).
2.2.1
Communications Technologies
Communications support is based on standardized communication technologies and protocols. For short-range connections IrDA (infrared data association) and Bluetooth are the most often used protocols. Protocols of the TCP/IP (transmission control protocol/internet protocol) suite are used for networking over a CSD (circuit-switched data) or GPRS (General Packet Radio Service) connection. Several messaging protocols are supported from simple short messages to e-mail and multimedia messages. For browsing both HTTP and WAP. However, the current version of the Series 60 Platform does not provide a programming interface to HTTP stack. The WAP protocol is used for delivering MMS (multimedia messaging service) messages in addition to browsing. TCP/IP suite is provided for networking and it enables usage of other protocols, such as SMTP (simple mail transfer protocol), POP3 (Post Ofce Protocol 3), and IMAP4 (Internet message access protocol 4). SMTP is a protocol used for sending messages (i.e. for uploading e-mail messages from a client application to an e-mail server). The same protocol is used to deliver messages between servers so that
28
the server used by the receiver will be reached. The receiver may download the message from the server by using either the POP3 or IMAP4 protocol. Several other applications may use protocols [TCP, UDP (user datagram protocol) or IP] from the TCP/IP suite as a bearer. To create an IP (UDP or TCP) connection to an Internet address, a connection to an Internet access point (IAP) must be established. For that purpose, a physical layer connection is created using either CSD or GPRS. PPP (point-to-point protocol) is used to transfer IP packets over a serial physical link. E-mail messages may be transmitted between the smartphone and network servers without an IP connection by using, for instance, the SMS service. The third messaging service supported by the Series 60 Platform is MMS. The MMS allows for the inclusion of sound, images, and other multimedia content in the messages. For short-range connectivity, there are several protocols that can be used. RS-232 is supported by the Series 60 Platform, although Nokia 7650 does not have an RS-232 port. Wireless connectivity protocols include IrDA and Bluetooth protocols, the latter using ISM (industrial, scientic, medical) radio frequencies. The detailed description of all protocols and their usage in own applications is provided in Part 3 of this book. Table 2.1 contains a list of supported communications technologies in the Series 60 Platform and their essential features. In addition to applications based on the standard technologies, new services and middleware may be provided. Examples include mobile portals, payment solutions, location-based solutions, advertising, and virtual communities. All messaging or data transfer protocols are implemented by using the same framework provided by Symbian OS. New protocols and the support of new message types may be implemented with plug-in modules, dynamically extending the capabilities of the phone.
2.2.2 Messaging
Messaging provides an ideal way of communication when no immediate response from the receiver is required. Messages may be stored in the server to wait for the receiver to download or be pushed directly to the receiver, if online. E-mail messages are an example of the former so-called pull model. SMS messages are delivered using the push model. The success of SMS messaging has shown how benecial it may be if the same standard has a worldwide support. Now the development is changing from SMS to MMS, with sound and image capabilities, creating a new dimension for chatting, entertainment, and person-to-person messaging. In addition to SMS and MMS, the importance of e-mail in
COMMUNICATIONS SUPPORT Table 2.1 Supported communications technologies Technology Bluetooth Description Short-range radio frequency communication Primary APIs RFCOMM L2CAP SDP BT security manager BT serial API IMAP4 POP3 SMTP Up to 107.2 kbps in one direction 960014 400 bps Up to 57.6 kbps operator and terminal dependent Speed Up to 1 Mbps Comment Raw speed
29
E-mail messaging
GPRS
Packet radio service for GSM cellular network Global system for mobile High-speed circuit-switched data Infrared data association protocol stack Multimedia messaging service Short message service Synchronization protocol transmission control protocol/internet protocol suite Wireless application protocol TCP UDP IP WSP WDP IrTinyTP IrMUX MMS
GSM HSCSD
IrDA
Up to 4 Mbps
MMS
Minimum maximum message size 30 kB 160 characters in one message Content protocol Depends on the physical bearer Depends on the bearer
SMS
WAP
Note: for abbreviations and denitions of application programming interfaces (APIs) see the Glossary.
corporate messaging should not be underestimated. E-mail messages may be uploaded and downloaded to the corporate server using the standard protocols and, if required, in a safe way by encrypting the content by, for example, using a secure socket layer. The Series 60 Platform provides an API for sending and receiving SMS, MMS, and e-mail messages. E-mail messages are transferred using the SMTP, IMAP4, or POP3 protocols. In addition to existing protocols and their APIs, software developers may implement their own plug-in modules for specic message types and messaging protocols. The messaging architecture takes care of checking, if the required
30
messaging protocol is supported. If it is, the architecture takes care of loading the required plug-in modules for transferring, editing, and storing messages as well as for notifying messaging events. The plugin architecture is not restricted to messaging; any protocols may be implemented using similar principles.
Smart Messaging
Smart messaging is messaging directed to applications residing on the phone. Nokia has dened an open standard called Nokia Smart Messaging (NSM; the specication can be found at www.forum.nokia.com). Symbian has dened an extension to NSM, named BIO messaging (bearer-independent object). The transport service for BIO messages can be, for instance, Bluetooth, SMS, or infrared. Smart messages are used to synchronize data for PIM (personal information management) applications or to transfer conguration settings and data for other applications. Data for PIM applications include vCard and vCalendar objects, which are used to synchronize phone book and calendar application entries. Conguration settings may be used to congure, for example, the WAP service, based on Nokia and Ericsson WAP conguration specication. In addition to that, smart messages may be used to deliver ringing tones, operator logos, and picture messages, which are all NSM-specic. Each message type has its own MIME (multipurpose internet mail extension) content type or port number by which it is recognized. In Symbian OS, the identication of each message type requires a BIO information le and, depending on the bearer, also the MIME type. The contents of this le and examples of smart messaging are provided in Chapter 17.
COMMUNICATIONS SUPPORT
31
to-do entries. However, to-do entries cannot be delivered inside vCalendar objects in the Series 60 Platform. Example items between PIM applications will be given in Chapter 18.
2.2.3
Browsing
Browsing of arbitrary content is difcult in a handheld device because of its limited memory and small display. The WAP protocol family provides functionality similar to the World Wide Web but is designed to accommodate smartphones and other handheld devices, having only a low bandwidth connection to the content server. WAP may be used for news browsing, gaming, online auctions, or chatting over several different bearers, such as SMS and GPRS. In the future, one of the most common ways to use WAP may be the transfer of MMS messages. WAP over GPRS provides fast connection times compared with circuit-switched data connection and, although the data is delivered in a packet-switched manner, there is sufcient bandwidth for WML (wireless markup language) content. HTTP stack is implemented in the Series 60 Platform, but the HTTP APIs are not available for C++ application developers. The Series 60 Platform supports WAP 1.2.1, which has many useful features for smartphones. In addition to normal content downloading, WAP settings may be transferred or content may be pushed into the terminal. WTAI (wireless telephony application interface) specication is also supported for standard telephony-specic extensions, such as call control features, address book, and phonebook services. Nokia has made a mobile Internet toolkit product available for application designers and content publishers to create WML content. The toolkit is available at www.forum.nokia.com.
2.2.4
32
MMS application
MMS server (Message type module) Symbian OS WAP (Wireless application protocol) server WAP session protocol (WSP) Wireless transaction protocol (WTP)
Connection agent
SUMMARY
33
storing, and for header manipulation. The body is created in the MMS editor. The main function of the MMS server MTM is to send the message. The MMS service uses the WAP stack to send and receive messages. The exact functionality will be explained in Chapter 17. The protocols in the WAP stack are accessed through the Symbian OS WAP server. This server is not a WAP server, providing WAP services, but an internal server sharing resources with WAP protocols. WAP datagrams are delivered over the IP protocol. The IP connection is created at an Internet access point using GPRS or CSD. Because IP has no knowledge how to route WAP datagrams, before the connection has been established it asks the network interface manager for a route. The manager uses a connection agent to create a route using the services provided by Symbian OS telephony server. The dashed line in Figure 2.7 indicates that the control is changed to the Telephony server, although data are not going to be delivered through these components. When there is a physical connection, the telephone module loans a port to the network interface manager, which then gives the port to the PPP protocol. Access to the GSM signaling stack takes place through an internal modem, the use of which requires the services of the serial communications server and device drivers.
2.3
Applications
Series 60 Platform provides not only ready-to-run applications but also a few reference applications. These provide a public API to get access to the application services. For example, the API of the photo album application provides easy access to the image nd service. A list of available applications are shown in Table 2.2 (Nokia, 2001c). In addition to the existing applications, users may download applications or develop new applications themselves. The rest of this book deals with software development for the Series 60 Platform.
2.4
Summary
The Series 60 Platform is designed for one-hand operated smartphones. All navigation, browsing, and selection functions of the user interface can be made with ones thumb. The platform contains a UI library called Avkon, which is designed to allow the implementation of usable and intuitive applications. The platform also contains a set of reference applications providing a public API, which may be used to access the services of the applications. The platform supports a
34
Table 2.2 Ready-to-run applications in the Series 60 Platform Application Phonebook Description Contact database integrated with messaging and other applications; supports vCard data format for visitor card exchange and synchronization Scheduling application; supports vCalendar data format A list of To-Do entries can be downloaded into this to-do list For text entries and editing Store for images Application management tool for the multi-tasking environment World clock, business calculator, and a selection of entertainment items Allows users to compose new tunes Client software for messaging applications Voice recorder, telephone settings, call logs and message indicators, user proles, call forwarding (divert), speed dialing, and voice dialing and voice tags For installing new software via the PC connectivity suite or over the network SyncML 1.0.1 synchronization engine; supports data transfer over mobile networks [wireless application protocol (WAP)], Bluetooth, and infrared data association (IrDA); supports vCalendar 1.0 and vCard 2.1 data formats Security settings and software certicate management
Calendar To-Do Notepad Photo Album Pinboard Clock, Calculator, Unit Converter Composer E-mail, SMS, and MMS Telephony applications
Security
wide range of standardized communications technologies for data synchronization, content browsing, messaging, and networking. The next chapter describes some useful design patterns that may be used in the application development. Also, the basic application framework classes used in every Series 60 application are explained.
3
Design Patterns for Application Development
Design patterns describe solutions to common software problems. They help software developers to apply good design principles and best practices of software development. Design patterns when applied properly improve the quality of the software with respect to, for example, reusability and maintainability. Design patterns are reusable software building blocks. They provide not only a common language for the designers in some problem area but also class and collaboration diagrams to be applied as well as documentation, implementation, and testing specications. Design patterns, however, have consequences, which must be taken into account before applying them. This chapter covers the most common and useful design patterns applicable in Symbian OS. Examples of using ModelViewController, Observer, ClientServer, Adapter, Microkernel, and State design patterns are given. Some patterns are applied in the design of a simple rockpaperscissors game. In addition to this, coding idioms characteristic of Symbian OS programming are provided. To understand class and the other diagrams used, the reader should have a basic knowledge of the UML (unied modeling language). Readers who are not familiar with UML may read, for example, the UML user guide written by its original designers (Booch et al., 1999).
3.1
36
During the gathering of requirements, the software developer tries to specify all customer and end-user requirements of the software. The requirement specication contains a description on the information and information ow, functionality, behavior, and validation criteria (Pressman, 1999) of the requirements. UML provides several tools for specifying and further analyzing the requirements. Information and information ows may be described using object diagrams and sequence diagrams. Use cases encapsulate functionality; the sequence diagrams describe different scenarios of this. Behavior description contains the handling of the user events and commands. UML state charts may be used in the behavior description. (Douglass, 2001). Validation criteria are used later in the software process to test whether the implemented software meets the specied requirements. This phase is called validation testing, which is one of the subjects of Chapter 7. The software developer analyzes each requirement and performs further investigation to recognize which classes may be used to encapsulate each object and what kind of relationships there are between the classes. The development process continues with the design phase, where the developer investigates how each requirement should be implemented. The design starts at the architectural level, specifying the system and its external interfaces. The system is then decomposed into subsystems. Functional decomposition divides complicated functions into a set of less complicated functions which are easier to design. More importantly, decomposition also helps in recognizing existing reusable subsystems. Design patterns are used in the design of the subsystems if a subsystem can be recognized as encapsulating a common software problem. One problem in the design process is how to handle changes in requirements. Change that takes place during the design process naturally also affects the design and often violates the original design. In addition to this, developers are often not motivated to check all effects caused by changes in the design. A good design should have high cohesion and low coupling. High cohesion means that a subsystem includes only those functions that are closely related to each other; low coupling means that interactions between subsystems are kept to a minimum. So, a change should affect only one subsystem, leaving others unchanged. One way to try to increase quality in software design is to apply design patterns during the design. They are commonly used in object-oriented software development to capture solutions to common software problems. Excellent tutorials to design patterns are those by Gamma et al. (2000) and Buschmann et al. (1996). As the whole Series 60 Platform is object-oriented there are many patterns applied in the implementation of the platform itself.
37
3.1.1
Table 3.1 Design pattern categories Purpose Creational Structural Behavioral Architectural patterns Abstract factory Microkernel ModelViewController Active objects Design patterns Factory method Singleton Class adapter Object adapter Template method Observer Exception handling Iterator Coding Idioms Two-phase construction Cleanup stack Thin template
3.2
38
Adapter
Client
Figure 3.1
Microkernel architecture
the platform and makes upgrading and customizing the platform much easier than a monolith architecture. The microkernel architecture is presented in Figure 3.1. The microkernel component in Figure 3.1 implements atomic services that are needed for all applications throughout the system. It maintains systemwide resources, such as memory, processes, and threads, and controls the access to them. It also provides the functionality for interprocess communication. Functions that cannot feasibly be included in the kernel because of their size or complexity are separated into internal servers. Internal servers extend the functionalities of the core. They handle, for example, graphics and storage media and may have their own processes or shared libraries loaded inside the kernel. External servers use the services of the microkernel and internal servers to provide services for the clients. They are heavily used in Symbian OS. External servers handle communications (Serial communications server, Socket server, Message server, and Telephony server), graphics (Window and Font and bitmap servers), audio (Media server), and storage media (File server). They are executed in their own processes. Each external server provides a client-side application programming interface (API) that encapsulates the interprocess communication between the client and the server. The adapter provides a transparent interface for clients, hiding, for example, the details of the communication. Adapters thus improve the changeability of the system.
39
the software robustness and reusability. The MVC pattern helps the software designer to fulll the object-oriented design principles, such as the Open Closed Principle (OCP; Martin, 1996). The idea of the OCP is that developers must decide early on in the analysis or design phase which parts of the system will be expanded later and which will stay xed. According to the OCP principle, the design is extended by adding new code and classes by inheriting existing base classes rather than modifying the existing ones. Completed and tested code is declared closed, and it is never modied (only errors will be xed). The MVC paradigm satisfying these principles is well-known and the main idea in the pattern is simple, as can be seen in Figure 3.2.
View Model
Reads
Updates
Manipulates
Controller
The MVC can be thought of as a low-level pattern and as an architectural, high-level, pattern. Architectural patterns can be implemented both on the operating-system level and on the application level. An example of an operating-system level architectural pattern is the layered user interface (Application ArchitectureControl EnvironmentUikonAvkon) in Symbian OS. Architectural patterns provide the higher-level abstractions and guide how the applications should be built within a specic environment. The architectural patterns normally advise which lower-level patterns can be applied during the program development. The MVC paradigm divides the application into three modules: Model: contains and manipulates the data in the program; View: denes how the data of the model is presented to the user; the view forwards received commands and requests to the controller; Controller: denes how the user interface reacts to received commands and requests. MVC divides the application into modules that are logically decoupled from each other. By doing this, the components are
40
more decoupled in the application. A decoupled component can be modied or removed without making changes to the other components. For example, changes to the Controller does not necessarily require changes to the View. Other design patterns can also be applied in MVC, such as composite, observer, factory method, and decorator patterns (Gamma et al., 2000). The composite pattern is useful when complex views are needed. This pattern enables the handling of individual objects and compositions of objects uniformly. The observer pattern denes how the observers can be notied and updated when the state of the subject changes. The factory method denes an interface for creating an object. The factory method is usually used in Symbian OS in the creation of a document of an application.
41
Application
AppUI 1
AppView
View Controller
the view do not necessarily cause changes to the engine. This is useful if there is a need to port the application to a different user interface (UI) style (Hoikka, 2001, pages 4849).
3.2.2
Adapter Pattern
Adapter is a very common design pattern. It provides software developers with a way to adapt to changing requirements without changing the structure of the original design. That is why adapters are used more often in the implementation phase than in the design phase. The adapter design pattern is also called a wrapper as it wraps some existing functionality into new environments. The adapter is essential in the design of the portable applications. The adapter can be implemented either as a class or as an object adapter. However, a class adapter is not interesting in Symbian OS because it requires the use of multiple inheritance. Figure 3.4 shows the implementation of an object adapter. It uses aggregation rather than inheritance (used by the class adapter) to control the adaptees
42
Client
Target
Adaptee
+<<virtual>>Request()
+SpecificRequest()
Adapter
+Request() +SpecificRequest()
Adaptee->SpecificRequest()
behavior. The client uses the adapter via interface, dened by the target. The adapter takes care of translating the client calls to the corresponding adaptees methods. The adapter is transparent for the client. The object adapter enables a single adapter class to be used with all adoptee type objects. The adapter can also add functionality to all adaptees at once. However, the object adapter has no way of overriding the adaptees behavior.
3.2.3
Observer Pattern
The observer denes a one-to-many dependency between collaborating objects. The observer enables the partitioning of a system into observers that react when their subjects change state. It is used in many event-based systems to separate the event source from the event monitors. The observer design pattern is shown in Figure 3.5. The concrete observers attach themselves to the subject in a way that the subject knows which observers to notify when its state changes. The observers register themselves to the subjects in which they are interested. A subject may have multiple observers, and an observer may listen to several subjects. The update method may contain a ag, indicating which subject changed state in the case of a many-to-many relationship. The problem with the standard observer pattern is that the type information gets lost if the subject or observer hierarchies are derived. A single observer does not know which subject subclass changed the state. There are, however, several special design patterns that solve the problem. Nevertheless, some of them are not applicable for Symbian OS environment because they require RTTI (run-time type indication) to work. RTTI can be seen as an extension to static (compile-time) type indication. It offers to the user information on
43
Subject Observer
+<<abstract>>Attach() +<<abstract>>Detach() +<<virtual>>Notify()
+<<abstract>>Update()
Concrete Subject
Concrete Observer
+<<virtual>>Attach() +<<virtual>>Detach()
+<<virtual>>Update()
pointers and references, which is similar to the type information a compiler maintains during compiling.
3.2.4
State Pattern
The intent of the state pattern is to provide an entity with the possibility of altering its behavior when its internal state changes. The state pattern also lets us vary the state-based behavior by modifying the state transitions and to reuse the behavior separately. The state pattern is shown in Figure 3.6. The state pattern describes a context, a state machine that denes the entity that has a state-based behavior. It also provides a uniform interface for the states. The interface is abstract in most cases but can also contain some state-shared behavior or data. The transition from one state to another is usually dened inside the concrete states, but it can also be dened inside the state machine.
Context State
+Request()
+<<abstract>>Handle()
Concrete state 1
Concrete state 2
+<<virtual>>Handle()
44
Declaring it inside the states decreases the need to modify the context when state transitions are modied or new states are added. The state change is invisible to the user; it has the same interface even though the inner functionality of the state machine changes. The state design pattern enables us to design very exible and expandable solutions. The state transition can be dened by the state subclasses or by the state machine itself. The difculty in implementing the state pattern arises when all the states use the same resources. The resources are often dened in the state machine, and the subclasses must get a reference to the owning class, which is not a very elegant solution.
45
this should be implemented in the function named ConstructL(). Finally, when it is safe (function leaves do not cause a lost of the pointer) the pointer is popped from the cleanup stack. The code example below shows how the idiom is used to create an engine object of the rockpaperscissors game. The rest of the design of the game is described below.
CRpsModel* CRpsModel::NewL() { CRpsModel* self = new (ELeave) CRpsModel; // Use of overloaded new CleanupStack::PushL(self); // Pointer pushed into the cleanup stack self->ConstructL(); // Second phase construction CleanupStack::Pop(self); // Pointer popped from the cleanup stack return self; }
3.3
3.3.1
Requirements Gathering
The goal of the game is very simple. The challenger starts the game by selecting one of three items: rock, paper, or scissors. The rock may be put wrapped inside the paper, which may be cut into pieces with scissors, which can be damaged by the rock. If, for example, the challenger chooses the rock, the challenged player must choose the paper to win. If the challenged player chooses the scissors, the challenger wins. If both players are using the same items, neither of them gets the score and the result is draw. The number of moves may be congured in the software so that, for example, after each three moves the challenge is sent. What are the requirements of this game? The challenger must be able to choose the item (e.g. using a GUI). In the Series 60 Platform an obvious key for selecting an item is the navigation key. The selection may be conrmed by pressing the key down. The selected item must be communicated to the other player (it should be possible to use
46
any supported communication technology). For communication we must dene the structure of the game PDUs (protocol data units; i.e. messages). The application can be launched from the shell but also when a smart message is received and directed to the application. Either player may be the challenger or the initiator of the game. The number of moves (selected items) should be congurable. After comparing the players items in the moves, the result should be shown to the user.
Use Cases
Use cases are utilized to understand users requirements (Douglass, 2001). They dene the cases how the user may interact with the system. The case denition includes input and output parameters, consequences, relations to other use cases, exceptions, and timing constraints. There is a notation for use cases in UML, but cases may also be specied in text. The rockpaperscissors (Rps) game may contain the following use cases. Case A: the user wants to create a game challenge and send it to a certain recipient User launches the RpsGame application from the Menu. The user selects a sequence of moves using the navigation key and user interface. The sequence of rocks, papers or scissors is shown graphically. The user selects Challenge from the options menu, which launches a smart message editor. The user lls in recipient number or address. The user selects Send, which causes the send of the message. Another use case species the situation in which the challenge has been sent to the user, as described below. Case B: an Rps smart message arrives
The user opens the message, either from Inbox or Soft notication. This opens the Rps smart message viewer. User selects Accept from the Options list. This launches the RpsGame applications. The user plays against the received challenge. Again a specic number of moves must be selected before the response is compared with the challenge. The user sends the result back to the other device.
47
3.3.2
Analysis
In the analysis phase the gathered requirements are studied further. First, we divide the UI part and game logic (engine, model) into their own components, as shown in Figure 3.7. The basic structure of the application follows the GUI framework, as in any Eikon (or Avkon) application. The separation of the user interface and the game logic makes it easier to test the application and use generic parts directly in other UI styles. The UI part takes care of the user events and application data, whereas the engine accesses the communications and the other system services, such as les, to send and receive messages between the players.
Application DLL
Engine DLL
3.3.3
Design
In the next phase, we consider what is required in the software so that it meets the set requirements (i.e. how it should be implemented). This is the place where design patterns are applied. The design of the UI framework of the application is straightforward. The application architecture already determines which classes to use for which purpose (i.e. which has the role of the controller, which one is the view, etc.). There are four basic base classes (application, document, applications user interface, and container) and the fth, which is independent of the application architecture and which implements the engine part. The application class contains the entry point of the application (i.e. the function used to start the application). The
48
document is used to create the application user interface (App UI). In le-based applications, the document class creates a layer between the user interface, the engine, and the le in which the engine will be stored. The App UI takes care of handling the user events, and the container represents the user interface itself (i.e. all controls to be shown in the user interface). The basic classes and their relationships are shown in Figure 3.8.
CEikApplication CEikDocument CAknAppUi CCoeControl MCoeControlObserver
CRpsGameApp 1
CRpsGameDocument 1 1
CRpsGameAppUi 1
CRpsGameContainer
CRpsModel
CBase
By studying the use cases it is possible to recognize situations in which we may apply design patterns. The user cannot, for example, send the challenge unless a certain amount of moves has been selected. The result cannot be calculated if either the challenge or the response is not available. Thus, in some states the application should respond to specic user requests only. More obviously, the states can be seen in communications. Because the state pattern increases the binary size of the application, we use just a single integer variable to indicate the state of the application. In the Series 60 Platform it is possible to, for example, hide some menu items in certain states. For example, in the game, the challenge menu item is hidden until the minimum number of moves has been selected. Some classes need to know if there are changes in some other class. In this case it is reasonable to apply observers. They observe the state of the subject and notify the observer class about state changes. In Figure 3.8 we can see that CRpsGameContainer is derived from CCoeControl and MCoeControlObsorver. The former is the base class of all controls, which may be drawn on the screen. The latter provides a virtual HandleEventL() function. This function is called
49
whenever the observed class calls ReportEventL() function. This enables the change of the view in the control in cases the view change in another control causes changes to this view as well. Observers are frequently used with asynchronous requests in the Series 60 Platform. They notify, for example, about message arrivals and service completions. In Figure 3.9 we have applied also active object design pattern. Messaging, and communications in general, is highly asynchronous. There is no reason to use resources for waiting in applications, so the execution of waiting objects may be suspended until the request waited for has been served. In Figure 3.9 there are three communication classes derived from CActive, which is the base class for active objects. Each active object may wait for the completion of a single request at a time. That is why it is common to use three active objects: one requesting a connection, one requesting data transmission, and one requesting data. The details of CSendAppUi are not shown in the gure. This class provides another way of creating and sending messages in addition to communicating active objects. The CCommsEngine class takes care of sending the message, when CAsendAppUi is not used. The message is created by the engine. It contains the moves of the user encapsulated in the CRpsMoves class. The moves (rock, paper, or scissors) are stored by the CRpsGameContainer class with respect to the selections of the user.
CRpsGameDocument 1 1 1 CRpsGameAppUi 1 1 CRpsGameContainer 1 CArrayPtrFlat
1 CRpsModel 1
CSendAppUi
CRpsMoves
CRpsMessage
CCommsEngine
1 CTransmittingAO CActive
CReceicingAO
Figure 3.9
50
CArrayPtrFlat is used to store the bitmaps of the paper, rock, and scissors. The container (view) is capable of showing the bitmaps, because it is a control (i.e. derived from CCoeControl see Figure 3.8). All controls are typically drawn on the screen, although there are container controls, which just contain controls but are never drawn themselves. A large part of the source code of the game engine will be presented in Chapter 5.
3.4 Summary
Design patterns describe solutions to common software problems. To apply a pattern, the problem must be identied rst. After that, the pattern provides the class and sequence diagrams, and, using these, existing components may be reused in the implementation. The most commonly used patterns in Symbian OS include MVC, microkernel, clientserver, adapter, observer, and state patterns. Some of these have also inuenced the architecture of the operating system itself to make it highly suitable for embedded systems, such as smartphones.
4
Software Development on the Series 60 Platform
After the design phase, which was the subject of the previous chapter, the software implementation starts. It is possible to use C++ or Java programming languages for software development on the Series 60 Platform. The development follows the same pattern regardless of the user interface (UI) style, although tools may differ. At least, there is a PC-hosted emulator providing a Microsoft Windows based implementation of the Symbian software platform. Microsofts Visual C++ 6.0 (VC++) is used for source le editing, compiling, and building. Other UI styles may use other IDEs. For Java development, any Java integrated development environment (IDE) can be used (e.g. CodeWarrior). When using Visual C++, instead of building against Win32, the software is linked and built against a Symbian header and library les, which are included as a part of the SDK (software development kit). The binary built is then run in the emulator. In addition to the emulator, there are, naturally, building tools for target hardware and many utilities, making software development easier. For Java there is an own SDK Nokia Series 60 MIDP (mobile information device prole) SDK for Symbian OS. This chapter covers all the necessary development tools and instructions on how to build software for the emulator and for the target phone. We also show how to install software on the phone and how to take into account internationalization and localization issues. The end of this chapter contains a list of web links of the Symbian community. The links may be used for getting help and support for software development. This chapter gives enough information to understand how to build the code examples in later chapters. As an example, we build the rockpaperscissors game and show which les have to be dened for build tools. All examples are available at www.digia.com/books.
52
53
Figure 4.1
54
At the same directory level to which EPOCROOT points, there is another directory Shared containing tools for application development, testing, and deployment. The most often-used tools are emulator, SDK help, bitmap converter, resource compiler, AIF Builder (application information le builder), and application installer. One tool Application wizard is located in NokiaTools directory in EPOCROOT. There are also GCC (Gnu Compiler Collection) and linker tools for making builds for the target hardware.
4.1.3
Application Wizard
Application Wizard is an excellent tool for starting to learn the application architecture and the classes related to it. It provides a graphical means of creating a minimal GUI application. This minimal application may naturally be extended to develop more complicated applications. The tool creates four basic application architecture classes: CXyzApp, CXyzDocument, CXyzAppUi, and CXyzContainer, where Xyz is the name given to the application. The use of these classes and the
55
Figure 4.2 A view of the AIF Builder (application information le builder) showing language and user interface style selection
application framework will be discussed in Chapter 8. In addition to the application skeleton source code, les required to create workspace and makeles are also created. Other tools, such as Menu Builder, may be used to develop the user interface further.
4.1.4
Build Tools
The tools delivered with the SDK make the building process simple. The environment neutral mmp project le of Symbian can be used to generate toolchain-specic project les for VC++ (emulator builds) and GCC (target builds). During the development, the project le manages all linking and building details. The project le also takes care that all outputs from the build and any required resources, such as resource les, icons, bitmaps, and sound les, are built into the appropriate location for debugging on the emulator. It is also possible to use the command line by using the same project le for creating required makeles. Makeles are generated with the makmake tool. The developer may use makmake directly. However, more often a Perl script is used to call makmake. The bldmake project building utility is used to create a .bat le, which calls a Perl script, which in turn calls the makmake tool. The user has to provide an information le (having an extension .inf) for bldmake, which in the minimal form contains only the names
56
of the project denition les (having an extension .mmp). These les may be generated automatically with Application Wizard or copied from example applications. The command (given on the command line) bldmake bldles generates abld.bat, which is invoked to call the Perl script calling makmake.
/* Example bld.inf file */ PRJ_MMPFILES RPSGame.mmp /* This is the UI part of the Rock-Paper-Scissors game */ RPSModel.mmp /* Model or engine of the game */ PRJ_PLATFORMS /* If you build for WINS, ARMS, ARM4 or THUMB, the platform does not need to be specified */ PRJ_EXPORTS /* Specify any files you want to copy some destination (default \epoc32\include) */ PRJ_TESTMMPFILES /* Specify any files needed for building test programs */
The project denition le denes the type of the build (e.g. application, server, library, device driver, protocol module). It is dened by targettype, but also by the UID number. The UID number has three 32-bit values, the rst of which indicates whether the le contains data or is an executable program. The second UID denes the subtype. For data les, the subtype identies the store (direct or permanent) containing the document associated with a specic application or an AIF, associated with the application. Stores are used to store streams, which are sequences of bytes. A complicated structure or object is externalized into several streams, as shown in Figure 4.3. The direct le store does not allow change of streams (overriding, deleting, replacing), but these functions are available for streams in the permanent le store. There are three kinds of executable les in Symbian OS: normal executables (.exe), used mainly for servers, static interface libraries (.dll), used for shared libraries, and dynamic interface libraries, used in the implementation of plug-in software modules (their extension being library-specic). For servers, the second and third UIDs are not needed. For libraries, the second UID identies whether the library is a shared library or provider library. In the case of a provider library, the UID also identies the type of library (e.g. application, message-type module, device driver, protocol module, etc.). For example, the UID value 0x100039ce denes that this executable library is an application. The third value uniquely identies the application, document, or data le. The third UID of the rockpaperscissors (RPS) game is 0x101F5BBD. For released software, the values in the range
57
Stream 2
int x
Stream 3
int x
Stream 4
0x010000000x0fffffff must not be used, since this range is reserved for testing purposes. Symbian manages the UID numbers, and developers may ask Symbian for UIDs for released software. This is done by sending an email to [email protected], the message specifying the number of required UIDs (typically, 10 at most). An example project le is given below. The last line species, how the AIF resource le is compiled. The given line species that we compile a RPSGameAif.rss resource le, located in ..\aif, into an .aif le, RPSGame.aif, having an icon and corresponding mask. The icon is shown in Figure 4.4.
58
The project le for the game engine library is much simpler. The second UID, 0x1000008D, reveals that the source les are built into a normal shared library:
ARGET RPSModel.dll TARGETTYPE dll UID 0x1000008d 0x101F5BBE SOURCEPATH ..\src SOURCE RPSModel.cpp RPSMessage.cpp RPSModelDll.cpp LANG SC USERINCLUDE . ..\inc SYSTEMINCLUDE . \epoc32\include LIBRARY euser.lib estor.lib
The abld script is used to create required build les and build the application, including any resource les. The resource le denes all the resources of an application, such as text strings, menus, dialogs, and other customizable screen elements. These are managed outside the application source code in separate resource les, which makes, for example, the localization of the software easier. To create build les for the emulator, i.e. WINS (Windows single process), the command abld build wins is used. In the same way, a target build is generated using the command abld build armi. Creating a workspace and project les for Visual C++, use command abld makele vc6. The .dsw makele is generated for applications which are going to be developed and debugged in the Visual C++ integrated development environment (IDE); this is a workspace le that can refer
59
to one or more project les with the extension .dsp; the makmake generates a dsp le which is like a makele used by the IDE. For target hardware, three different executable binaries, or application binary interfaces (ABIs), may be generated: arm4, armi, and thumb. The plain binary for the ARM (Advanced Risk Machines) is arm4 build, which has a slight performance advantage over armi. However, arm4 does not interwork with thumb, which is the smallest build in terms of binary, because 16-bit rather than 32-bit instructions are used. The only binary that interworks with both thumb and arm4 is armi (arm interworking), and that is why this binary build should be used by third-party software providers. The relations between the binaries are shown in Figure 4.5 (Pora, 2002).
arm ABI
thumb ABI
armi ABI
Note that there are necessarily several differences between emulator and target builds. One of the most obvious ones is that in Windows the software is run in a single process, whereas in the target several processes can be created. For example, in the target hardware a new
60
process for each application is created, but in the emulator only a new thread for a new application is created when the application is launched. Since the processes are used for memory protection, there is no similar memory protection between applications and other software components in the emulator as in the target builds.
4.1.5 Emulator
Emulator is used to test and debug the software before deploying it in the target hardware. After building the application for WINS the emulator may be launched, and the application icon should appear on the display of the shell program. This can be done by pressing Ctrl F5 in Visual C++. For the rst time, Visual C++ prompts for the location of the executable to be run (this executable is the emulator). The debug emulator is located in the %EPOCROOT%\epoc32\release\wins\udeb\ epoc.exe directory. After loading the emulator, the applications can be launched as shown in Figure 4.6, in which we start the RPS game. The debugging is done in the same way as the debugging of any Windows application. It is possible to add breakpoints and step through code as normal. After testing throughout, the software may be uploaded to a real device. Since the binary format in ARM is different from Windows, the software must be rebuilt for armi by using abld build armi urel on the command line. The binary les may be uploaded directly using Symbian OS Connect (see Chapter 18) or creating rst an installation package with the Sisar application.
4.1.6 Sisar
Sisar is an application for creating installation packages. An application typically consists of several les, such as executable, binaries, and resource les for supported languages. The Sisar application packages these les into a single installable .sis le.
APPLICATION DEPLOYMENT
61
62
First the name of the component is given in all supported languages, in our case in English and Finnish. All .sis les require a UID, which is given next. Although the installed les do not require a UID, the .sis le does require it. The version is given using three numbers. In the example, 1,0,0 species version 1.0, with build number 0. All numbers may be in decimal or hexadecimal format. After the version number, there may be package options, which may be either SH (SHUTDOWNAPPS) or NC (NOCOMPRESS). The rst options specify that applications should be closed during installation. By default, SH is unselected. By default, the .sis le is compressed, which may be changed by using the NC option. Finally, the package type is dened. The package may contain an application SA (SISAPP) or any system component: SY or SYSSYSTEM (shared library); SO or SISOPTION (dynamically loaded component, code, or data); SG or SISCONFIG (congures an existing application); SP or SISPATCH (patches an existing component); SU or SISUPGRADE (upgrades an existing component). All Nokia products based on the Series 60 Platform will use a builtin mechanism to check that the installed software is really Series 60 software. For this purpose, each Series 60 application should have an id-sequence identifying the software platform. The lack of the sequence results in a warning message. However, the user is still able to install the software. The id-sequence is the same for all Series 60 applications and is added into the .pkg le right after the header. The added line should be exactly like the one given below.
(0x101F6F88), 0, 0, 0, {"Series60ProductID"}
The next line (package signature) is optional and is included when the installation le is digitally signed:
APPLICATION DEPLOYMENT
*private-key-file-name,public-key-certificate-file-name
63
The signature is checked and the user may check the details of the certicate when the package is installed. The rst le name species the private key le, from which the digital signature is created (see Chapter 15). The second refers to a le name which contains either the corresponding public key certicate or the certicate and its associated certicates, used to form a certicate chain. A third parameter may be used to specify a password to access the private key le, if it is encrypted.
Optional Lines
The rest of the le includes optional package lines. These are: condition blocks used to control the installation; option lines used to display a list of options to the user; language-dependent (only one is installed depending on the selected language) and language-independent les (installed regardless of the language); capability lines (used in the determination of the device or application capabilities); requisite components (components required by the installed component and present in the target); embedded .sis les (installed and also removed, when the main component is installed and removed); and comments (any lines preceded by a semicolon). The condition blocks are used to control the installation. With them it is possible, for example, to use one installation le only to support any number of different Symbian OS phones. A condition in the condition block may be a condition primitive. There are NOT, AND, and OR operators available to combine individual conditions. A condition primitive may be a relation between an attribute, such as manufacturer, and a value. For example, manufacturer value 0 is Ericsson, as shown in the following example:
IF manufacturer=0 ; Ericsson "ericsson\rps.app"-"!:\System\Apps\rps\rps.app" ELSEIF manufacturer=1 ; Motorola "motorola\rps.app"-"!:\System\Apps\rps\rps.app" ELSEIF manufacturer=2 ; Nokia "nokia\rps.app"-"!:\System\Apps\rps\rps.app" ELSE "unknown.txt"-"", FILETEXT, TEXTEXIT; Specifies that "unknown.txt" is ; shown in a dialog box and not installed on the target. TEXTEXIT ; specifies that Yes and No buttons are used in the dialog ENDIF
See SDK Help to read the exact syntax and other attributes and their corresponding values for the conditions. A (!) character allows the user to specify the drive letter.
64
The options line is used to ask the user to make selections affecting the installation. It is preferable to put these at the beginning of the package format le, so that options are asked at the beginning of the installation, although this is not required. Options are built-in attributes, that have either value 1 (selected) or value 0 (not selected). The value may be checked by using condition blocks, as above. For example, the following options could be used to ask the user if she or he wants to include Bluetooth and multi-player modules in the installation:
!({"Add Bluetooth Component","Lisa a Bluetooth-komponentti"}, ; Option 1 {"Add Multi-player Component","Lisa a monen pelaajan tuki"}) ; Option 2
Those les for which the selected language does not affect the installation are listed in the language-independent le lines. The line species the source and target directories for each installed le and, optionally, arguments that specify the type of le: FF or FILE (default value); FT or FILETEXT (text le shown in a dialog box during installation, but not installed into the target); FN or FILENULL (will be installed later); FM or FILEMIME (le is passed to an application, specied by MIME type); and FR or FILERUN (installed in the Symbian OS device). There are other arguments used to specify how the text dialog is cancelled, or when the installation le is run (used with FILERUN); for example, to open up a text document, describing the application:
"source\components\Math.dll"-"!:\system\libs\Math.dll"
Language-dependent les are, for instance, resource les, discussed further below. For example, for our RPS game, we could use the following line for language-dependent les:
{ "\source\apps\rps\group\rps.ruk" "\source\apps\rps\group\rps.rfi"}-"!:\system\apps\rps\rps.rsc"
The requisite components are specied with the UID, version number, and the name of the required component. The version must be at least the required one. The name does not have to match the component name. It is provided simply to give information to the user. Embedded .sis les may be added in almost the same way. The user has to specify the source .sis le and its UID. Look at the example below:
{0x10001111},1,0,0, {"My Math library"} ; Requisite component @"YetAnotherComponent.sis",(0x10001112) ; Embedded .sis file
AIFB Files
In addition to package format les, sisar can import AIF Builder project les (.aifb). From these les, sisar reads the application UID and extra
65
bar captions for the application. The .sis component will be set to support those languages specied in the .aifb le. The .sis le is generated simply by using the GUI of the sisar. The Installation File Generator will generate the .sis le according to the guidelines of the imported package format and AIF Builder project les. The .sis les may then be delivered to the target device by using any supported communications media. The execution of the .sis le in the target causes the installation les to be copied into the correct locations.
4.3
66
For detailed examples and instructions of the tools, language codes, syntax, and use of resources, refer to Series 60 SDK.
.hrh .rh
.h
.rss
.bmp
Resource compiler
Bitmap converter
.cpp
.rsg
.rss
.mbm
AIF tool
.exe
.rsc
.aif
Figure 4.7 File types (white boxes) and tools (light-gray boxes) used in the resource compilation process; for a description of there les and tools, see the list in text
The purpose of the les and tools illustrated in Figure 4.7 is as follows: The C++ compiler and linker together take source les (.cpp) and produce output (.exe or .dll, or .app, or les of a similar extension). The resource compiler will convert a resource source le (.rss) into a compiled resource le (.rsc) containing the resources that the executable program will use. It also produces a generated resource header le (.rsg), which contains the symbolic IDs of these resources. The .rsg le is included in the .cpp le, so that the C++ compiler has access to the symbolic IDs of the resources that will be used. C++ class denitions are specied in a source header le (.h). Resource struct statements are specied in a resource header le (.rh). An application will include its own .rh le only if it requires its own struct statements. Flag values are dened in a le that must be available to both the C++ compiler and the resource compiler: the .hrh extension is
67
used for this, and .hrh les are typically included in the .h le that denes the classes (for C++), and the .rh le that denes the structs (for the resource compiler). The bitmap converter combines the original bitmap les (.bmp) into a multi-bitmap le (.mbm). The Aif builder uses .rss and .mbm les to build an application, information le (.aif). The .aif le species the icon, caption and embedding capabilities of an application.
4.4
68
4.4.1
Licensee Resources
Symbian has created a special extranet for the licensees of Symbian OS. Also, licensees of the Series 60 Platform are able to access this extranet as Symbian OS is a part of the Series 60 Platform. It holds all current documentation relating to generic technology projects for all Symbian OS releases. The extranet includes, among other things, specications, plans, schedules, progress reports, and any other useful documentation that licensees may need. Access to this database is obtained by licensing the Symbian OS. Current Symbian licensees and their was addresses are listed in Table 4.1
Table 4.1 Current Symbian licensees and their web addresses Licensee Nokia Kenwood Siemens Ericsson Psion Sanyo Matsushita (Panasonic) Motorola Sony Sony Ericsson Fujitsu Web address www.nokia.com www.kenwood.com www.siemens.com www.ericsson.com www.psion.com www.sanyo.com www.panasonic.com www.motorola.com www.sony.com www.sonyericsson.com www.fujitsu.com
69
4.4.3
Developer Resources
The list given in Table 4.2 gives addresses of developer networks and other websites providing additional support (which this book does not cover) primarily for independent software developers and vendors. Additionally, some marketplaces are listed for those wishing to sell or buy software that is based on Symbian OS.
Table 4.2 Developer resources Resource Symbian developer network Directories for resources related to Symbian OS Forum Nokia Nokia marketplace Ericsson developer zone Motorola developers Digia services and support Java support All about Symbian OS version ER6 Tucows marketplace Web address www.symbian.com/developer www.symbianpages.com www.forum.nokia.com www.softwaremarket.nokia.com www.ericsson.com/mobilityworld developers.motorola.com/developers www.digia.com http://java.sun.com www.allabouter6.com www.tucows.com
4.4.4
Table 4.3 Symbian OS training resources and events Resource or event Symbian OS training Symbian OS STP Digia STP Training Symbian Events Web address www.symbian.com/developer/training www.symbian.com/partners/part-train.html www.digia.com/digiawww/home.nsf/pages/Training+Services www.symbian.com/news/news-events.html
4.4.5
Development Material
In addition to this book, a lot of other material is available to support development related to Symbian OS in addition. Some of these and their web address are listed in Table 4.4.
70
Table 4.4 Interesting development material related to Symbian OS Development material Professional Symbian Programming book Wireless Java for Symbian Devices book Symbian OS Comms Programming book Programming Psion Computers book Code Warrior for Symbian Devices Free-of-charge Series 60 SDK, tools, and documents Symbian Developer Network
Note: SDK, Software Development Kit.
4.5 Summary
The Series 60 SDK provides a rich set of tools enabling an efcient means of to developing applications. In the build process, Perl scripts are used to create work spaces for the Visual C++ IDE and makeles for GCC. After that, applications are built either in the IDE or on the command line. Other tools may be used for minimal application creation, bitmap conversion, AIF generation, and for preparation of an installation package. In the next chapter we start writing the source code for the application. In addition to examining the existing applications, the Symbian Community may be used to search for help during the development process.
5
Platform Architecture
The programming characteristics of the Series 60 Platform and the underlying Symbian OS originate mainly from Microkernel, Clientserver, ModelViewController, and Observer design patterns in addition to idioms related to careful management of resources, such as memory. This chapter gives an overview of the platform architecture from the application engine programming point of view. We concentrate mainly on Symbian OS programming and leave the details of graphical user interface (GUI) programming to Chapter 8. Using the engine of the rockpaperscissors (RPS) game as an example, we describe processes, threads, libraries, multi-tasking, the clientserver framework, ling, memory management, and the use of descriptors.
5.1
System Structure
It is possible to implement three kinds of executables in Symbian OS: shared libraries, provider libraries, and server executables. The type is specied in the project le (.mmp), as shown in the previous chapter. In addition, there are differences in the implementation of the executables themselves. For example, all libraries must have an E32Dll() function as one entry point, but server executables require an E32Main() function and have no entry points. Shared libraries have an extension .dll (dynamically loading link) in Symbian OS. Libraries may be dynamically loaded or unloaded, if there is no software component using the library. There is at a maximum one instance of a shared library in the memory at any moment in time. In case of previous software component have already loaded the library, its reference count is increased when another software component uses the same library. The reference number indicates the number of applications sharing the library. When the reference count
72
PLATFORM ARCHITECTURE
is decreased to zero, there is no application using the library any more, and it may be unloaded. The interface of the library is dened by entry points, which are members of a class declared with IMPORT C macros in the header le and EXPORT C macros in the implementation le. In the RPS game the engine has been implemented in its own shared library. Thus, there could be several GUI applications sharing the same engine code. The interface of the engine is dened as follows: The most important function is AddDataFromReceivedMsgL(), which is called from the document.
#include <e32base.h> #include "RpsMessage.h" class CRpsMessage; class CRpsMoves; // CLASS DECLARATION /** * Manages the game data. The protocol allows only one * outstanding challenge. */ class CRpsModel : public CBase { public: IMPORT_C static CRpsModel* NewLC(); IMPORT_C static CRpsModel* NewL(); IMPORT_C ~CRpsModel(); public: /** * Adds data of received msg to a model. * @return ETrue if the message was valid, and EFalse * if not. */ IMPORT_C TBool AddDataFromReceivedMsgL ( RFileReadStream& aStream ); /** * Checks, whether the player has a challenge message * @return iChallenge member variable */ IMPORT_C TBool HasChallenge() const; IMPORT_C TBool HasResponse() const; /** * Sets the challenge member variable, if challenge msg * exists */ IMPORT_C void SetChallenge( TBool aChallenge ); IMPORT_C void SetResponse( TBool aResponse ); /** * Returns challenge moves from the message * @return challenge moves (e.g. rock-rock-paper) */
SYSTEM STRUCTURE
IMPORT_C const CRpsMoves& ChallengeMoves() const; IMPORT_C const CRpsMoves& ResponseMoves() const; private: CRpsModel(); void ConstructL(); private: // data CRpsMoves* iMove; CRpsMoves* iResponseMoves; CRpsMoves* iChallengeMoves; TBool iResponse; TBool iChallenge; CRpsMessage* iMessage; // Received message };
73
The function checks if there is any challenge message sent to this application. If there is, challenge moves are read to the memory and the player creates and sends a response message to the challenger. In case there is no challenge message, the player becomes the challenger of the game. Other functions are used to set and get the role of the player and return the moves in the challenge or in the response. What is missing in the above example? There is no E32Dll() function. The function is implemented in a separate le together with our own Panic() function. The Panic() function requires two parameters: a category and a reason. Because the category is the same throughout the whole engine, we have implemented a function, that requires only the reason code:
#include <e32std.h> // for GLDEF_C #include "RpsMessage.h" // Panic enums GLDEF_C TInt E32Dll( TDllReason/* aReason*/ ) { return (KErrNone); } void Panic( TInt aPanic ) { User::Panic( KRpsModelPanic, aPanic ); }
Two other classes of the library (CRpsMoves and CRpsMessage) are declared below. These could be implemented in their own library to increase possible reusability even further, but in the RPS game they are part of the same library as the engine. First, we have dened global enumerations for message type and move type. The main function of the CRpsMoves class is to store and handle individual moves. The type and owner of the move may be get and set with corresponding functions. AddMoveL() calls AppendL() to store a move in an array. We have used the CArrayFixFlat class,
74
PLATFORM ARCHITECTURE
because stored elements (moves) have a xed size. The at array does not have as good a performance as segmented arrays in the case of frequent insertions and deletions of elements. We have made an assumption that a typical game consists of a few insertions and, at most, one deletion. The difference between at and segmented arrays is that the at array has only one contiguous buffer, including all array elements. A segmented array has several buffers in the memory segmented together. Count() returns the number of moves in an array. This function is used, for example, in calculating the nal score, when all elements of an array are gone through. Finally, elements may be deleted with a Delete() function. The received message is stored into a le, which is read and written by the CRpsMessage class. It calls CRpsMoves to read the moves from the message. Reading and writing are handled by the InternalizeL() and Externalize() functions. Other classes take care of opening the le store and just pass a stream as a parameter to read and write functions. The code is as follows:
#include <e32base.h> #include <s32file.h> #include "RpsGameDocument.h" //CONSTANTS _LIT(KRpsModelPanic, "RpsModel.dll"); enum TRpsMessageType { EChallenge, EResponse, EResponseAndNewChallenge }; enum TRpsMoveType { ERock, EPaper, EScissors }; // FUNCTION PROTOTYPES void Panic( TInt aPanic ); // FORWARD DECLARATIONS class RReadStream; class RWriteStream; // CLASS DECLARATION /** * Contains an unlimited number of game moves, i.e. a Rock, Paper * or Scissors sequence. */ class CRpsMoves : public CBase {
SYSTEM STRUCTURE
public: enum TRpsMessagePanic { ENoMovesArray, EIndexOutOfBounds, EChallengerMovesAlreadySet, EResponderMovesAlreadySet, ENoResponse, ENoChallenge, ESessionIdNotFound, EBadIndex1, EBadMoveIndex, ELastIsntUnansw, EBadType1 }; enum ERpsRespOrChallType { EResponse, EChallenge }; enum ERpsMoveOwner { ESelf, EOpponent }; public: // construction & destruction IMPORT_C static CRpsMoves* NewLC(); IMPORT_C static CRpsMoves* NewL(); IMPORT_C ~CRpsMoves(); public: /** * Returns, whether this is a response or challenge move. * @return type of the move. */ IMPORT_C ERpsRespOrChallType Type() const; IMPORT_C void SetType( ERpsRespOrChallType aType ); IMPORT_C ERpsMoveOwner Owner() const; IMPORT_C void SetOwner( ERpsMoveOwner aOwner ); /** * Adds a new move to the move array. */ IMPORT_C void AddMoveL( TRpsMoveType aMove ); IMPORT_C void DeleteMove( TInt aIndex );
75
/** * @return the number of moves in the move array. */ IMPORT_C TInt Count() const; /** * Returns the selected move (integer index).. * @return move type (paper, scissors, rock) of a selected move. */ IMPORT_C TRpsMoveType Move( TInt aIndex ) const; /** * Resets the move array. */ IMPORT_C void Reset();
76
PLATFORM ARCHITECTURE
IMPORT_C void InternalizeL( RFileReadStream& aStream ); IMPORT_C void ExternalizeL( RWriteStream& aStream )const; private: CRpsMoves(); void ConstructL(); private: CArrayFixFlat<TInt>* iMoves; CArrayFixFlat<TInt>* iResponseMoves; CArrayFixFlat<TInt>* iChallengeMoves; ERpsRespOrChallType iType; ERpsMoveOwner iOwner; };
CRpsMessage represents a data message, which is sent between players. In addition to the moves, it adds (writes) and reads (removes) the sender name eld of the message. The message structure is dened in this class. If it is going to change, the InternalizeL() and ExternalizeL() functions have to be changed:
/** * Represents a data message that is sent between players. * The message can contain a response or/and a challenge. * If it contains both, * then the challenge is a new challenge. * The protocol allows only one outstanding challenge. */ class CRpsMessage : public CBase { public: IMPORT_C static CRpsMessage* NewLC(); IMPORT_C static CRpsMessage* NewL(); IMPORT_C ~CRpsMessage(); public: IMPORT_C void SetSenderNameL( const TDesC& aName ); IMPORT_C const TDesC& SenderName() const; /** * For accessing the challenge moves. */ IMPORT_C const CRpsMoves& ChallengeMoves() const; /** * For accessing the response moves. */ IMPORT_C const CRpsMoves& ResponseMoves() const; /** * Reads the message from the file. */ IMPORT_C void InternalizeL( RFileReadStream& aStream ); IMPORT_C void ExternalizeL( RWriteStream& aStream ) const; private: void Reset(); private: CRpsMessage(); void ConstructL();
SYSTEM STRUCTURE
private: HBufC* iSenderName; CRpsMoves* iChallengeMoves; CRpsMoves* iResponseMoves; };
77
If the library is released, it is important to remember to freeze the interface to support binary compatibility. Freezing (using the command abld freeze) generates a .def le, from which the import library will be generated. The import library is used to map entry functions of the library to ordinals. The library contains an export table, mapping the ordinals to memory addresses (offsets from the beginning of the library) of the entry points. In Figure 5.1 three library types and the use of an import library and export table is shown.
Server executable Load provider library Call function at ordinal 1 Unload library ProvLibraryX.dll Exports table 1_offset1 2_offset2 3_offset3
Server executable Import table libraryx.lib Code F1(); F2(); _______1 _______2 _______3
There is one common thing shared by all libraries. They all have to provide an E32Dll() function. This function must also be implemented in provider libraries but it must not be the rst entry point (ordinal 1) in the provider library. The difference from the shared library is that the interface has already been dened, and it typically contains only one entry function at ordinal 1. This function is called to create an object from a concrete class, which is derived from the abstract interface. There are several types of provider libraries [applications (.app); control panel applets (.ctl); MIME (multipurpose Internet
78
PLATFORM ARCHITECTURE
mail extension) recognizers (.mdl); protocol modules (.prt); and device drivers (.pdd and .ldd)]. For application provider libraries, the entry point is the function NewApplication(), as shown in the example below; note also the existence of the E32Dll() function, although its implementation is empty:
EXPORT_C CApaApplication* NewApplication() { return new CRPSGameApp; } // --------------------------------------------------------// E32Dll(TDllReason) // Entry point function for EPOC Apps // Returns: KErrNone: No error // --------------------------------------------------------// GLDEF_C TInt E32Dll( TDllReason ) // GLDEF_C used to prevent E32Dll to // be at the first ordinal { return KErrNone; }
Server executables having an extension .exe do not typically have any entry points, because communication with the client is taken care of by using interthread communication (ITC). A server implements the E32Main() function, which provides an application programming interface (API) for the operating system to start the executable. The E32Main() function returns the address of the ThreadFunction to be called. The RPS game uses several servers, for example, for accessing the communications services. One server, which practically all Symbian OS programs use, is the single-threaded kernel server. The kernel server provides, for example, access to device drivers. In addition to the kernel server, also the Window, Socket and File servers are used by the game. More information about using servers is provided later in this chapter, in Section 5.2.5.
79
detail below). In the target, each application and server creates its own process, but also a user may create new processes. All processes can access the shared libraries and the system ROM. It is possible to dene four priority values for processes in the user mode (EPriorityLow=150, EPriorityBackground=250, EPriorityForeground=350, EPriorityHigh=450). This priority is used to calculate the overall priority for a thread, which is created in the process. The developer may also use an absolute priority value, in which case the process priority is not used. There are ve priority levels available for threads executed in the user mode: EPriorityMuchLess, EPriorityLess, EPriorityNormal, EPriorityMore, and EPriorityMuchMore. The kernel has a privilege (i.e. higher priorities for processes and threads). A thread is a unit of execution. Threads are scheduled based on the thread priorities or round-robin if the threads have the same priority. The scheduling is preemptive, which means that a higherpriority thread may interrupt a thread having a lower priority. In some cases, preemptive multi-tasking is not required; it is sufcient to implement cooperative multi-tasking. This is what we have used in our game, which is actually single-threaded. The switch between threads (especially when the threads are located in different processes, and a context switch is required) is heavier than to schedule active objects, implementing the cooperative multi-tasking framework. As mentioned above, there are two execution modes: user and kernel modes. The kernel always has a higher priority compared with the processes and threads in the user mode. Between these two modes, there are two libraries, EUser and kernel executive, both of which provide a large set of services to applications. The EUser is used to handle processes and threads, memory management, active objects, etc. The kernel executive is used to access, for example, device drivers. The EUser library is our next topic. The RPS game is single-threaded. However, active objects are used in communications for cooperative multi-tasking. We will show the code examples in Part 3 of this book.
5.2
80
PLATFORM ARCHITECTURE
5.2.1
Memory Management
Each process must contain at least one thread. The bare process cannot be executed, but threads can. A new thread is created with a Create() function, whose signature is as follows:
TInt Create(const TDesC& aName, TThreadFunction aFunction, TInt aStackSize,TInt aHeapMinSize, TInt aHeapMaxSize, TAny *aPtr,TOwnerType aType=EOwnerProcess);
In the function parameters, a name for the thread, thread entry function, stack size (8 kB by default; see E32STD.h), minimum (256B) and maximum (no default value) sizes for the heap, and a pointer to the parameter of the thread entry function must be specied. When a thread is created, a new memory chunk is allocated for the thread. The chunk is a memory area having contiguous virtual memory addresses. Physically, the chunk contains the required number of allocated memory pages, the size of which depends on the processor architecture (4 kB in ARM). The lower part of the chunk is reserved for the stack, and the upper part for the heap, as shown in Figure 5.2. The stack always grows downwards, so it is never possible for the stack to grow into the heap area. Heaps may be shared between threads by using a different version of the Create() function. Instead of determining the size limits for
Figure 5.2
81
the heap, a pointer to an existing heap is supplied. This provides an easy way for communication between threads.
CBase
All objects allocated in the heap should be of the type-C class, meaning that they are derived from a common base class CBase. There are two properties shared by all C classes. The CBase class provides a virtual destructor that allows instances of derived classes to be destroyed and cleaned up through a CBase* pointer. All objects derived from CBase can be pushed by CBase* pointers into the cleanup stack and destroyed by using the PopAndDestory() function of the CleanupStack. There is also a new operator for the CBase base class. This operator calls User::Alloc() to allocate a memory cell in the heap. It also initializes the CBase derived object to binary zeros, i.e. members, whose initial value should be zero do not have to be initialized in the constructor. This, in turn, makes it safe to destruct partially constructed objects. Most engine classes in the RPS game are C classes.
Cleanup Support
Since the heap is not automatically cleaned up there is a risk that the memory cells are not deleted, which means the application leaks
82
PLATFORM ARCHITECTURE
memory. All resources, and obviously also allocated memory cells (and actually the whole memory chunk), are freed when the thread that has created that chunk dies. Of course, we must not use memory management in this way, because it is possible that some applications are run for years before the phone is rebooted. That is why developers should make a leak-free code. A situation in which a memory leak may take place occurs if we use automatic variables to store pointers to allocated memory cells. If we leave the function in which the variables were dened, they are lost and we have no way to delete the cells anymore. In Symbian OS, the way to store pointers in situations such as this is to use the cleanup stack. The cleanup stack is a special stack for storing automatic variables that are handles (so that they can be closed after a possible leave) or pointers to allocated cells. If a leave occurs, each pointer stored in the stack is used to delete the allocated memory, and no memory leaks occur. Below, we provide a typical example of two-phase construction and the use of a cleanup stack to create a C class:
EXPORT_C CRpsModel* CRpsModel::NewLC() { // Allocation of the objects in the heap CRpsModel* self = new (ELeave) CRpsModel; CleanupStack::PushL(self); // Allocation of the objects created by this object self->ConstructL(); return self; }
Developer should use overloaded new operator, new (ELeave) instead of just new. The ELeave parameter tells us that this operation (allocation for object) may leave. By using ELeave the developer does not have to check whether the return value of the constructor is NULL or some other valid value. This problem is bigger in compound objects because although the allocation is successful for the object itself we cannot be sure, whether all other objects owned by this object have been properly created. If the object has been successfully constructed, a pointer to that object is pushed into the cleanup stack. We then execute lines of code, which may cause a leave. If the leave has not occurred, the pointer is popped from the cleanup stack after we are sure no leaving can cause the loss of that pointer. The second-phase constructor, shown below, creates new objects owned by the engine:
void CRpsModel::ConstructL() {
EUser: SERVICES FOR APPLICATIONS iChallengeMoves = CRpsMoves::NewL(); iResponseMoves = CRpsMoves::NewL(); iResponse = EFalse; iChallenge = EFalse; iMessage = CRpsMessage::NewL(); }
83
Note that it would have been safe to assign two T classes already in the default constructor, because space has been allocated for them before assignment. However, challenge and response moves as well as an instance of the message are created in the constructor. All C classes are instantiated using NewL() or NewLC() factory functions instead of the default constructor. This ensures that memory allocations are made in a safe way. Allocations in the stack are automatically freed, but the developer has to take care to free allocated cells in the heap memory. Destructor functions take care of deleting allocated heap objects:
EXPORT_C { delete delete delete delete } CRpsModel::~CRpsModel() iMove; iResponseMoves; iChallengeMoves; iMessage;
Note that the constructor should never trust that the allocation of an object has been complete. Trying to delete a non-existing object is a programming error that is why in CBase-based classes members are initialised to 0.
5.2.2
Exceptions
Exceptions are used in Symbian OS in a different way than they are used in standard C++, because the gcc version 2.7.2 used earlier did not support C++ exceptions. Symbians TRAP macro and User::Leave() calls are analogous to try/catch and throw in C++. Any piece of code that might leave (i.e. call User::Leave() or any other leaving function) is executed inside the TRAP harness. When an error occurs, (e.g. memory allocation fails), Leave() is called, which obviously leaves the executed function, unwinds the call stack, and returns the most recent TRAP harness, which catches the exception. The software may try to recover or may then just panic (i.e. kill the current thread). There is a clear difference between exceptions and panic situations. Exceptions are used in case, where it could be expected that something will go wrong. The most typical example occurs when we cannot
84
PLATFORM ARCHITECTURE
allocate memory because of the Out-Of-Memory (OOM) situation. Another situation could be that the requested resource is temporarily unavailable. What should you do? You should not panic, because a temporal denial of service is not an error. Thus, you should throw an exception and handle the exception in the trap. In cases where there is nothing to do to recover the software, panics are used. Panics typically reveal the existence of a programming error. A common error is that the developer exceeds the limits of a descriptor, for example. The example code below shows, how a programming error may be revealed:
EXPORT_C TInt CRpsMoves::Count() const { __ASSERT_ALWAYS( iMoves, Panic(ENoMovesArray) ); // has ConstructL been called? return iMoves->Count(); } void Panic( TInt aPanic ) { User::Panic( _L("RpsModel.dll"), aPanic ); }
The Count() function returns the number of moves if an instance of CArrayFixFlat has been created. It is a programming error, if the array does not exist, when the function is called. Asserts are very useful for checking the soundness of the external variables of the class. Note, also, the use of our own Panic() function, described earlier. By using it there is no need to specify the same category (RpsModel.dll) in each function call. The second phase constructor for the CRpsMoves class is as follows:
void CRpsMoves::ConstructL() { iMoves = new (ELeave) CArrayFixFlat<TInt>(KNumberOfMoves); }
So, a panic occurs in Count() if the array to store the moves has not been created. However, if the creation fails in ConstructL(), a leave occurs already there. The constant KNumberOfMoves species how many moves must be selected before a challenge can be created or responded.
5.2.3 Descriptors
Descriptors are frequently used in Symbian OS programming instead of normal C++ strings. There are ve descriptor classes that can be instantiated: TBuf, TBufC, TPtr, TPtrC, and HBufC. TBuf and
85
TBufC are called buffer descriptors and their differ from TPtr and TPtrC pointer descriptors with respect to the owned data. Buffer descriptors own the data, but pointer descriptors have only a pointer to the data located somewhere else (in a buffer descriptor or memory address). Descriptor classes ending with a letter C have a constant API, which means that the API does not contain functions to change the contents of the descriptor. All descriptors except HBufC can be allocated in the stack. HBufC is allocated in the heap, although it is not C class. Note that there is no HBuf descriptor. The contents of the heap descriptor may be changed through an instance of TPtr. An example of using the heap descriptor is as follows:
EXPORT_C void CRpsMessage::InternalizeL( RFileReadStream& aStream ) { Reset(); aStream.ReadUint32L(); // sender name TUint8 nameLength = aStream.ReadUint8L(); if( nameLength ) { HBufC* nameBuf = HBufC::NewLC( nameLength ); TPtr namePtr( nameBuf->Des() ); aStream.ReadL( namePtr, nameLength ); CleanupStack::Pop( nameBuf ); iSenderName = nameBuf; } // Challenge moves iChallengeMoves->InternalizeL( aStream ); iResponseMoves->Internalize( aStream ); }
We will use stack descriptors frequently in communication engines in Part 3 and will not repeat the same code example here. The InternalizeL() function reads the sender of the message, after which challenge and possible response (in case this is a response message) moves are read from the stream by using the corresponding functions of the CRpsMoves class. The Reset() function empties previous moves from the move array. The rst part of the message is an unsigned byte indicating the length of the senders name. The name is read from a le to a heap descriptor. First, we create a descriptor object and allocate enough space for it to store the name. The Des() function returns a modiable pointer descriptor to the data in the heap descriptor. This allows a change of contents of the buffer, although the programming API of HBufC does not allow it. ReadL() reads the name to the descriptor, which is then assigned to iSenderName member. Note that NewLC() leaves a pointer to the created heap descriptor in the cleanup stack, and it must be popped by the developer. Finally, the
86
PLATFORM ARCHITECTURE
moves are read to move arrays by using the corresponding functions of the CRpsMoves class.
87
TUser is a class storing the nickname of a user in the chat application. We create a new type using a templated TPckg. Then we create a new object of this new type and store the content of an object iUser (of TUser type) to the created object. The address of the created package descriptor can be used in the SendReceive() function.
5.2.4
88
PLATFORM ARCHITECTURE
The event loop has been implemented in the active scheduler. When the scheduler is started (and an active object has issued a request), the scheduler calls User::WaitForAnyRequest() function. This call decreases the value of the semaphore of the thread by one. If the value becomes negative, the thread starts waiting for any completed requests from the server. After completing the service, the server signals the thread that requested the service. If the semaphore value becomes zero or positive, the thread may start execution. In addition to the Signal() call, the server also changes the value of the iStatus variable. If everything has succeeded, the value KErrNone is assigned to the variable. The active scheduler selects the active object, that has issued a request and has the highest priority. It calls the RunL() function of this object and the object may then handle the completion of the service. RunL() should be short, because it cannot be preemptied by other active objects in the same thread. If the active object does not want to wait for the completion of the request, it should call Cancel(). This function calls DoCancel() implemented by the user. Typically, in the DoCancel() function, resource-specic cancels are called, and any handles that are open are closed. Figure 5.3 shows the whole lifecycle of the active objects.
Engine Create active scheduler Active object Create active object and add it to scheduler Request service and call SetActive() Server Set active objectss iStatus to KRequestPending
WaitForAnyRequest
89
5.2.5
ClientServer Framework
The use of servers is typical of microkernels. With microkernels, they help to keep the system small. Servers also allow the isolation of resources and a safe way to share resources compared with the situation in which each client uses the resource itself. Servers are implemented in two parts. The server itself is implemented as an executable, for which a new process is created (in target builds). The other part is the client-side API, providing access functions to communicate with the server. The client-side API is implemented in a shared library, which any software component may use. The most important class is derived from the RSessionBase class, which provides a CreateSession() function. This function is used to create a session (i.e. a communication channel between the client and the server). There is one drawback in the use of servers. Because servers are executed in another process, there is a context switch between the client and the server processes. The context switch in Symbian OS means storing the data from the data section to the home section when a new process is restored from the home section to the data section. The home section occupies the lower memory addresses of the address space.
Filing
Filing is also implemented according to the clientserver framework in Symbian OS. In the RSP game we use les to read received messages. This is implemented in the TryLoadDataWrittenByMsgViewerL() function. The message application stores a message into a specic le, dened by the KMsgFileName constant. To access this le, we rst need a session to the le server. The session is created with a Connect() function, which calls RSessionBase::CreateConnection(). After that we create a subsession. The creation is embedded in the Open() function of the RFileReadStream class. If the le cannot be found, there is no challenge, which means that we are starting the game. In the other case, the engine reads the contents of the message. Note that the reading function in the engine may leave. That is why we should push the le session and le read stream handles to the cleanup stack. If the leave occurs and we lose the handles there is no way to close them but kill the thread. Because the engine is single-threaded this would mean killing the whole engine. By using the CleanupPushL() function, the PopAndDestroy() function takes care of closing the handles automatically:
90
PLATFORM ARCHITECTURE void CRPSGameDocument::TryLoadDataWrittenByMsgViewerL() { TFileName name(KMsgFileName); RFs fsSession; fsSession.Connect(); CleanupClosePushL(fsSession); RFileReadStream readStream; if ( readStream.Open( fsSession, name, EFileRead ) != KErrNone ) { // Couldnt find the file, so start a new game. iModel->SetChallenge(EFalse); CleanupStack::PopAndDestroy(); return; } iModel->SetChallenge(ETrue); CleanupClosePushL(readStream); iModel->AddDataFromReceivedMsgL( readStream ); CleanupStack::PopAndDestroy(2); // readStream and // file session }
The object of type RFileReadStream is given to the engine from the document. Engine calls the Internalize() function of the CRpsMessage(), which reads the sender, as shown earlier in the section Descriptors, and calls InternalizeL() of the CRpsMoves class shown below:
EXPORT_C void CRpsMoves::InternalizeL ( RFileReadStream& aStream ) { TUint8 count = aStream.ReadUint8L(); for (TInt n = 0; n < count; n++) { AddMoveL( (TRpsMoveType)aStream.ReadUint8L() ); } }
The implementation is rather straightforward. The rst byte indicates the number of moves and each move occupies one byte.
91
starts from the document class, which creates the engine and rst checks, if there is a message sent from the other player. If there is a message, the players role is responder. Otherwise, the player is challenger. The roles are set and get with trivial functions, as follows:
EXPORT_C TBool CRpsModel::HasChallenge() const { return iChallenge; } EXPORT_C TBool CRpsModel::HasResponse() const { return iResponse; } EXPORT_C void CRpsModel::SetChallenge( TBool aChallenge ) { iChallenge = aChallenge; } EXPORT_C void CRpsModel::SetResponse( TBool aResponse ) { iResponse = aResponse; }
If the player is challenged, the challenger moves are read using the following function. First the moves are read into the member of the CRpsMessage class and copied from the message class to the engine one move at a time:
EXPORT_C TBool CRpsModel::AddDataFromReceivedMsgL ( RFileReadStream& aStream ) { iMessage->InternalizeL( aStream ); TInt nof_moves = (iMessage->ChallengeMoves()).Count(); for( TInt i = 0; i < nof_moves; i++ ) { iChallengeMoves->AddMoveL( (iMessage->ChallengeMoves()).Move( i ) ); } return ETrue; }
The AddMoveL() function adds TRpsMoveType objects into a at dynamic array capable of storing xed-size elements (CArrayFixFlat):
EXPORT_C void CRpsMoves::AddMoveL( TRpsMoveType aMove ) { iMoves->AppendL( (TInt)aMove ); }
92
PLATFORM ARCHITECTURE
The storing is handled by the AppendL() function. If the array is full, AppendL() tries to expand the array buffer. It there is not enough memory, it leaves. In the other case, the array is increased by its granularity, for example, by ve elements. That is why the CArrayFixFlat array is called a dynamic array. There are other classes for storing elements whose size changes and to store elements in a segmented rather than in a at structure in the memory. The functionality of the CRpsMessage class is almost nothing else but read and write the message contents to the le. SetSenderNameL() is used to set the senders name:
EXPORT_C void CRpsMessage::SetSenderNameL( const TDesC& aName ) { HBufC* name = aName.AllocL(); delete iSenderName; iSenderName = name; }
Other functions return the challenge-and-response moves and are implemented in the same way as the corresponding functions in the engine. The UI part of the application will be described in Chapter 8.
5.4 Summary
Compared with other operating systems, Symbian OS is rich with tricks and techniques which help the development of more robust software and make programming easier. These techniques originate from microkernel architecture and strict requirements set to software components with respect to memory management, for example. Symbian OS programming involves use of system servers, management of memory to prevent memory leaks, an own exception handling mechanism, descriptors, active objects, and so on. As we have shown in this chapter, even the implementation of a simple application engine requires that software developers be familiar with these techniques, not to mention GUI programming and communications programming, discussed later in this book. The next chapter is the rst step towards GUI design, after which we discuss software testing before moving on to GUI programming.
6
User-centered Design for Series 60 Applications
User experience encompasses all aspects of the end-users interaction with the company, its services, and its products. The rst requirement for an exemplary user experience is to meet the exact needs of the customer, without fuss or bother. Next comes simplicity and elegance that produce products that are a joy to own, a joy to use (Nielsen and Norman, 2002)
In recent years, usability or user experience of the product has emerged as one of the key elements of market success in the software industry. Even though everybody can nowadays admit that a product must be easy to use, good user experience cannot be taken for granted. The product and its user experience have to be designed. The discipline of designing usable products is called user-centered design (UCD). There has been much research in this area, and in addition to being termed UCD (Bevan, 2002), it is called usability engineering (Mayhew, 1999; Nielsen, 1994), contextual design (Beyer and Holtzblatt, 1998), human-centered development (Norman, 1999) or interaction design as termed by Alan Cooper (Nelson, 2002). The fundamental goal of these design processes is the same, although the methods may differ. In the following sections we discuss how UCD can be applied in the application development for the Series 60 Platform. The rst section introduces the overall process for UCD. There are then sections describing studies on end-user needs (Section 6.2) and concept design workshops (Section 6.3). Section 6.4 focuses on the challenges of interaction design for smartphones. Section 6.5 elaborates the process of writing user interface (UI) specications. Finally, the setting of usability requirements and verifying usability are discussed (Section 6.6). An image editor application (Digia ImagePlus) developed by Digia is used
94
as a case-study example of applying UCD, and an example of a UI specication is given in Appendix at the end of this book.
6.1.2
Multi-disciplinary Teamwork
To get the best results and fast iteration cycles, UCD requires multidisciplinary teamwork. A good team includes representatives from marketing, engineering, and user experience functions. In the early concept design phase, the entire team gathers user-needs data and designs the concept in workshops iteratively until the structure of the product starts to become clear. After that, the team members may focus on detailed specication work in each area of expertise and meet regularly for clarifying the details and reviewing the specications.
95
Figure 6.1
During the development phase, while the engineering project is developing the product based on the specications, and marketing is focusing on product management, the user experience team designs UI details and graphics and veries usability with developed prototypes or early product versions. Commonly, the display texts are localized and the user manual is written in the later phases of development. A solid change management process is needed to take care of those inevitable changes that occur when usability is veried.
6.1.3
96
Graphic designers make the look of the product elegant and pleasing. Their skills are needed especially in products that contain new UI elements or graphical content. UI prototypers create rapid simulations of the developed products. With prototypes, usability verications and design corrections can be made sufciently early, before the actual product is ready. Usability specialists organize usability requirement setting and verication for the product. These may be the same persons as the user-needs researchers. User manual writers have skills for writing customer documentation for the product. They may also have responsibility for nishing and localizing the display text language. Often the same person may take several roles and responsibilities in a design and development project. To get the best results, there should be at least two user-experience persons in the project working as a pair and helping each other in creating and verifying the user experience. A good pair consists of a person with usability evaluation skills and a person with interaction design skills. UCD does not necessarily need to be a heavy and resource-intensive exercise, but, even with small efforts (e.g. the creation of paper prototypes) the design team can achieve better results than doing nothing in relation to end-users needs.
97
In the next section, the methods for observing end users and analyzing user-needs data are briey introduced.
6.2.1
98
Figure 6.2
99
Figure 6.3 Data display on a design room wall: observing end users produces a lot of important data
The analyzed user-needs data is then a starting point for concept design, which is discussed next. The data can be transformed into electronic format for later use and sharing. Standard word-processing and chart-drawing PC tools can be used.
6.3
100
Methods for concept design workshops will be discussed in the following sections. The content refers a lot to the contextual design process that is used and applied in Digias product design process. The workshops can be divided into the following phases: brainstorming, storyboarding, draft functional specication, and paper prototyping with end-user evaluation.
Design Ideas
Reading the user-needs data on the wall, each team member can develop dozens of concept, technology or UI ideas that solve the user needs or problems. It is good to start from individual idea creation with design ideas and to continue with the team vision, as described in the next section.
Vision
A useful target for brainstorming is to create a team vision; that is, scenarios about the developed product as used in the future. The team creates stories about end users using the developed product or system. The best design ideas can be gathered as starting points for the
101
scenarios. One team member starts the story, describing the end user and the task, and the others continue adding new ideas, while the vision is drawn out on a ipchart. When the brainstorming is based on the user-needs data it usually stays on the right track. If the design team is developing a product that is part of a larger system, it creates a story that covers the entire system in a way that is coherent within a users life.
Design Drivers
One brainstorming possibility is to pick up the design drivers from the user-needs data (Wikberg and Keinonen, 2000). The design team can identify a number of design drivers that emerge from the user-needs data. One example of a design driver for an image editor is, for example, the importance of emotional and humorous messaging among teenage users. These drivers are the design guidelines that are kept in mind throughout the development. They can be the starting point for usability and design requirements that are formalized with more detail after a few concept design iterations. Setting usability requirements is discussed in the section on usability verication (Section 6.6).
6.3.2
Storyboarding
After brainstorming, the team continues to design the detailed task sequences of the new product. They create storyboards or high-level use cases from each intended task for the planned product. In these step-by-step storyboards, each piece of paper describes one step of the users task or the response of the product to the users action. When the storyboarding is based on the task sequences from the user-needs study, the new design can be adapted to natural task ows and context of use. One does not need to be an artist to create simple storyboards, as seen in Figure 6.4; everybody in the team can participate in the drawing. A larger team can be divided into subteams, and each subteam can be assigned a different task to be drawn. The created storyboards are then evaluated by the entire team, issues are collected, and stories xed. It is important that the evaluation be focused on functional and interaction problems; detailed UI issues should be handled later, after the structure of the product is clear. After the evaluation, the team can continue to analyze the product structure and create a draft functional specication, as described in the next section. Storyboards can also be nalized by graphic designers and can be used for communicating product ideas to management.
6.3.3
102
Figure 6.4
A good way to specify and evaluate the structure of the application is to create a user environment design (UED), with a functional specication notation used in contextual design. UED is a quick way to write down the functionality of the design. It allows the team to concentrate on designing, not documenting, and to move on to paper prototyping. The UED structures the states of the product into focus areas, based on the coherent work or task that the user is doing. The UED is created from storyboards by identifying the focus areas, assigning the user and system functions to each focus area, as well as highlighting the links between focus areas based on the natural task ow. It excludes detailed UI elements, thus turning the focus onto structural issues. The UED is maintained during the concept iterations and it can be the basis for the detailed UI specication. A well-structured UED is a good starting point for designing UI variants to other platforms. Engineers like the UED, since it describes the essential requirements in a form that can be used for detailed use cases and architectural design.
CONCEPT DESIGN WORKSHOPS Table 6.1 Notation used in user environment design Heading or symbol Focus area Purpose Description
103
The focus area is a collection of functions that are a coherent part of the users work This describes briey, in the users words, what work is done in the focus area An open circle indicates a system function; this refers to the case where the system does something automatically (e.g. displays a screen or plays a tone) A closed circle indicates a user function; this is invoked to do the users task (e.g. a command in the Options menu) A function is written in parentheses when it is needed in multiple focus areas [e.g. (copy/paste function)] A single arrow indicates a link between two different focus areas (e.g. as when selection of a list item opens a new view with different functions) A double arrow indicates a double link, where two different focus areas exist in the same context. This is not very common in the Series 60 Platform because of the small screen size but some examples exist (e.g. an active call indication is displayed at the top right-hand side of the screen, while a calendar is open at the same time)
(global function)
A quick way to evaluate a concept design is to create a paper prototype. It is a very simple tool and is a not very cool technology but it suits well the concept evaluation purposes (Snyder, 2001). The design team sketches draft UI layouts on the basis of the storyboards and the UED. Post-it notes are good for representing Series 60 displays, and the phone mockup can be made of cardboard. Figure 6.5 illustrates a startup view of the image editor paper prototype. Each focus area usually means one application view on the display. User functions can be assigned to menu options or key commands. System functions are items on the display, information notes, or hidden functions occurring inside the software or network. Alerts and other audio components can be prototyped by human voice. The Series 60 UI style guide can be used as a reference, although the design team should not get stuck on UI details; these can be xed later (Nokia, 2001g). As soon as the rst paper prototype is created, it is then given to a sample of end users for evaluation, preferably in a real context of use. Three or four end users are enough for one evaluation cycle. The team can work in pairs; one person is a computer, changing paper displays while a test user interacts with the prototype, and the other person takes notes, as shown in Figure 6.6. The cardboard prototype is given
104
Paper prototype test made in a real context: note taker (left), user (middle) and computer
105
to test users, and they conduct their own tasks with the prototype; the designers can do some interviewing or observation before the test to nd out the relevant tasks from the users. The users own data from their current tools is lled into the prototype to make interacting with the prototype relevant. When testing the paper prototype in a mobile environment, the computer can use removable tape for attaching paper displays to the notebook pages and a cardboard device. Carrying the entire prototype is thus easier, and displays will not y away with the wind. The test users generally respond positively to the test situation and are eager to work with the prototype. Since the prototype is low-tech they understand that it is just an idea of the nal product. This invites them to give improvement ideas, to notify the test pair of structural problems, and to ignore irrelevant UI details in the early phase of the design. Often, a test session changes into a co-design mode, where the designers redesign the concept with the users. After the test sessions the team analyses the results, redesigns the concept, and updates the UED based on the ndings. If it seems that there are still structural issues in the concept, the paper prototype testing is iterated again. After a few test iterations, the structure of the application should remain stable and only UI issues should arise in tests. This means that the concept is ready, and product development with detailed interaction design and technical specications can be started. A specic requirement specication can be elicited from the user-needs data and the UED, in addition to business and technical requirements.
6.4
6.4.1
106
Some of the main characteristics affecting interaction design of the smartphones are as follows: They are usually designed for special purposes. Mobile phones are used mainly as telephones, but they do support some other tasks. The tasks supported by the device are simple information management tasks, such as taking notes, saving telephone numbers, managing meeting times, and to-do lists. An increasing number of devices can connect to various data sources with different protocols. Also, the peer-to-peer connectivity is an important function to allow the sharing of data with other users. Smartphones can usually connect to a desktop computer to synchronize or backup data. With data connectivity, devices are becoming the main communication device for some people, with short message service (SMS), e-mail, and a multimedia message service (MMS). With multimedia messaging, the user interface needs to be exible to accommodate picture and text viewing and sound and video replaying at the same time. The text input is slower when compared with desktop computers. Two basic ways of inserting text can be identied: telephone keypad, and stylus with character-recognizing software or a software keyboard that is used by tapping the stylus. The UIQ UI style uses a stylus, and the Series 60 UI style uses a telephone keypad (See Figure 6.7). Whatever the method of text input, it is important for designers to recognize the need of the application. For example, an instant messaging application will not be usable if the text input is difcult and slow for the user. (For more information on UIQ, see Symbian, 2002a). Some devices are designed to be used with one hand; at least the most important tasks such as answering an incoming call can be done with one hand only. Sometimes, the stylus is used for the more complex tasks. Here also, the need of the application has to be recognized, for example, a phone with a stylus interface has to have some kind of hands-free function to enable note taking while a call is active. The mobile context of the use is a big issue when designing the interface, and sometimes it is a neglected aspect. The user might be walking, carrying things, and using the device at the same time. Changing light conditions and noise can also affect the usability of the interface by distracting the user. These are all usability factors that cannot be veried in normal laboratory tests. To be on the safe side, it is good to build an ergonomic model by collecting information on how the users use the products while on the go,
107
Figure 6.7 Two Symbian OS smartphone user interface styles: UIQ (left) and Nokia Series 60 (right)
and what the disturbing factors in the environment are that may affect the use of the product. The disturbing factors could be, for example, bumpy roads, changing lighting, or rush hour on public transport. If the application increases the stress of the user in an already stressful environment, it is a good reason to redesign. Designing a small interface often results in a modal interface. The application is said to be modal if, for instance, it does not let the user begin a new task when in the middle of an unnished task. The application contains different modes for different tasks. In the desktop computer world, designing a modal interface is usually considered a bad idea for usability (Raskin, 2000), but most graphical interfaces have some modality. With small screens it is almost impossible to avoid. The same visual language used in the desktop computer will not be effective on the smartphone. The pixels reserved to give a threedimensional effect on the user interface usually take too much space of the small screen to make the use effective. For the same reason, the window paradigm is usually not used (Holmqvist, 1999). As seen in Figure 6.7, Symbian UIQ has a slightly larger display, with 208 320 pixels compared with Nokia Series 60, with 176 208 pixels. UIQ is designed mainly for two-hand stylus interaction, whereas
108
Series 60 is based on single-handed usage with a joystick (for the navigation and selection keys), soft keys, and phone keypad. Most of the UI controls such as dialog boxes or menus of the UI libraries (Avkon for Series 60, and Qikon for UIQ) are also different. Owing to the differences, an application designed for Series 60 cannot be compiled directly to UIQ, and vice versa. And as applications designed for them are not fully source compatible, binary compatibility also does not exist. Porting from one UI style to another is, however, straightforward and does not necessarily involve great effort. Many parts of the user interface need to be redesigned for making a variant of a third-party application (e.g. to another UI style). Different screen size may require splitting application data to different views. Joystick interaction and pen interaction may require a totally different approach for applications such as the image editor. Also, menu functions can be arranged differently from Series 60 Options menus and the UIQ menubar. Basically, all the UI functions need to be checked and the usability of the changes veried when creating a version of the application to another UI style even if the functional structure and UED of the application is intended to remain the same.
109
applications. Such new interaction mechanics are demanded in the direct manipulation of objects, such as image editing, moving a pointer in the screen, dragging and dropping objects, and so on (see Figure 6.8). These are not originally used in the Series 60 UI style.
Figure 6.8
Applications with totally new interaction mechanics, such as applications with the above-mentioned direct manipulation, need more careful usability testing than do applications that use an existing UI style. However, once the interaction has been tested it can be used for other purpose too. All new interaction mechanics should be veried with a software prototype. Paper prototyping may be a reasonably effective way to verify the usability of applications using an existing UI style. A software prototype is the best tool for verifying complex and detailed interactions that cannot be simulated with a paper prototype.
6.4.3
110
design workshop, a sample device or an emulator can be taken into the workshop to inspire the design process. The emulator, a hardware device, or the Series 60 UI style guide can be used to track any conicts between the new application and the UI style of the existing applications. When new applications are designed, the following issues, at least, should be checked: If any of the existing applications (also on desktop computers) already have similar keypad shortcuts they should be used for consistency. When system functions such as folder views, image browsing, contact-book browsing, and calendar browsing are needed, the Series 60 system default views should be used to preserve consistency with other applications. In addition, the Notes, Queries, and the Options menus should be used as they are used in the original software. The style guide gives very good examples of these (Nokia, 2001g). Basic UI elements should not be used in a non-standard way unless there is a very good reason. For example, if the application needs a view that opens automatically after the application launch, with multiple input options, the Options menu should not be used; a query with appropriate prompt text is the correct display to use. For example, selecting New message in the Messaging application opens a query with a prompt and three options. Consistent language throughout the whole application should be used. For example, the system command for closing the application is Exit, not Quit or End. All other commands should be as logical, such as Edit for modifying existing data. If the application uses a language other than English, the existing conventions for naming should be used. If the application is, for instance, a calculator for accountants, it is a good idea to use the terminology found in spreadsheet software. The logic of the menu structure should be checked with tests. Press of the select key can be used as a quick and natural selection key instead of picking a command from the Options menu. The select key can also open a collection of important functions in the OK options menu. This should be used sparingly; the OK options menu is even more task-specic than the Option menu. Back stepping with the Back softkey should be natural and bring the user to the expected view. This is a good case for paper prototyping to test.
111
In the application design, it should be remembered that the system focus is always moved to the incoming call, which can interrupt any task at hand. The user has to choose either to answer the call or to reject the call. Only after that can the work be continued. This kind of an interruption in a desktop computer might be annoying, but in smartphones it can be accepted; after all, they function mainly as telephones (see Figure 6.9).
The Options menus in Series 60 are always context-sensitive. Only the most relevant functions for the view or task are displayed. In this way, excessively long option lists are avoided; the correct functions can be reached quickly. Designing the Options menu requires very careful planning and task analysis. A paper prototype should be used to verify the correct order of the functions. Pressing the select key is generally used for the most important function of the Options menu. Pressing the select key can also open an OK options menu that contains functions strictly related to the selected object. For the difference between the Options menu and the OK options menu in the Contacts application, see Figure 6.10. It is advisable to avoid designing an application that forces the user to look for information in other applications to complete a task. Pressing and holding the applications key provides one way to overcome this restriction; the user can jump to another location in the device and
112
Figure 6.10 The OK options menu and the Options menu in the contacts application: the OK options menu (left) contains only the most important functions from the Options menu (right)
Figure 6.11 The applications key of Nokia 7650: this key can switch from one application to another
switch back to the task that was interrupted (see Figure 6.11). The copy/paste function also helps to avoid tedious writing of text and therefore also minimizes spelling errors. Both the applications key and the copy/paste function are signicant advances in the interaction of Series 60, since the early mobile phone user interfaces did not allow either.
113
If the application uses modes, they should be used in such a way that the user is informed when the mode is on or that the user holds a modier key pressed down. Raskin (2000) states that pressing and holding a modier key is easier for the user to remember than pressing once to switch on and pressing another time to switch the mode off. One example of the mode indication is the text input modier indication in the navi pane (Figure 6.12). The edit key (ABC) can also be used to switch between modes in new applications other than the text input modes. The edit key is the only key that can be pressed down simultaneously with another key. Other mode indicators can be: changing the application icon, changing the application title, changing the text in the navi pane, and so on.
Figure 6.12 The text input modier indication in different states: number input mode (left) and text input mode (right) (highlight by author)
6.5
6.5.1
114
data input and output, how the application connects with the operating system in the device, and how the application connects with the cellular network and network servers. From the properties described in the UI specication we know how the application behaves in the real world. A typical UI specication is a documentation of how the end user is going to use the product. Consumer software products are often produced by a team of experts, each with their own area of specialized knowledge. The UI specication document can serve as a common ground for discussion and communication on the product. The UI specication is representative of the product when the product is under development. Each member of the team has his or her own interest in the product, and therefore different expectations of the UI specication exist: The customers want to see that their requirements are all covered and that a solution for their problem is found. The customer then accepts the funding and timetable of the project. The person responsible for the usability plans the usability test according to the UI specication and use cases. A heuristic evaluation can be made, too, with the UI specication, using the usability aspects list, described in the section on usability verication (Section 6.6). The testing engineer makes the functional test plans with the help of the UI specication. The project manager assigns the relevant resources to work on different parts of the product. The marketing and sales managers get an idea of what the application does so that they can sell it to the right people. The manual and help writer writes the manual with the help of the UI specication. The software architect denes the technical architecture of the product, and the software engineers implement the features of the product according to the architecture and UI specications. The translator needs the UI specication to translate the user interface to different languages. The interaction designer needs the UI specication to maintain and document the design decisions between iterations.
115
UCD or by a person who has been evaluating the particular user needs for the product or who is otherwise familiar with a typical user. It is also possible that a software engineer writes the UI specication. However, it is not recommended that the UI specication be written by someone who does technical implementation simultaneously with the same application (Norman, 1999). The difference between programming and UCD make it very difcult to keep good user experience in mind when at the same time thinking of the internal programming logic of the software. Although one person writes the UI specication, the result cannot be optimal if there is no communication between other team members. Good results can be achieved only with team effort and user testing with the intended users. The reviewing of the UI specication should be done mainly by product-management and engineering staff. Even when bringing in input and comments from outside the team it is important to keep the focus on a good user experience of the product. The writer of the UI specication can also arrange walkthrough sessions with other experts to evaluate design ideas at an early stage.
6.5.3
6.5.4
116
raw structure of the application and a couple of commands that link from one view to another. This is usually sufcient for making a paper prototype and testing the concept with end users or for discussing the concept with customers. Avoid making too detailed a specication of the user interface too early. Sketchy designs command a more creative approach from the designers and test users. If the design looks too ne it is mentally difcult to make the necessary changes to features. Also, from an efciency point of view, it is a waste of work to nalize a design that is going to be changed after a usability test. Only after a number of usability test cycles can it be ascertained that the design works for the users. It is more cost-efcient that the changes to the design be made to the UI specication than to the program code after several weeks of programming.
6.5.6
117
when planning the functional testing of the application but also when demonstrating how the application works in real-world situations. Thus, for example, it can be veried whether any changes are really needed. An example of a use case is given in Appendix (page 493). In the early stage of product development it is important to get the structure of the application reviewed and approved by the team. When this is done, the ne adjustment of the details can begin. This is typically the most time-consuming stage of the work. Usually, it helps if the engineers are closely engaged in the project from the start so that they can start to plan the architecture while the UI specication is being written. The engineers can also help to clarify the details. The specication should be reviewed by the team, or walkthrough sessions should be arranged if discussion of the details is needed. If someone in the organization has previous experience of an application of the same type, they can act as outside reviewers. Another interaction designer can also help by reviewing the UI specication. When the specication is considered complete it can be tested with a prototype. Refer to the section on usability verication for more information (Section 6.6).
6.5.7
118
comments on the circulating copy of the document. The reviewers should be informed what are the most important issues that need reviewing in the UI specication, and, additionally, what issues can be ignored. The reviewers time should not be wasted in irrelevant issues.
Lists
Lists are used to display ordered data. Sometimes the list view can be displayed in grid form (e.g. the application grid in Nokia 7650). The lists are often customized for a particular purpose; compare for example, the week view with the day view in the calendar application (Figures 6.13 and 6.14). The specication should answer the following questions: What kind of a list type is used? Is the list item one-lined or multi-lined? What is displayed on the line or lines? Where do the data come from? Is there an icon column used with the list? Can the list be marked?
119
Figure 6.14
Icons
Icons are used to differentiate list items from one another. The list icons can also change to indicate a changed state of the list item (e.g. the Inbox icon in Messaging application changes appearance when a message is received). An application icon is used for branding of the application or to display indication of the temporary application modes. The specication should describe the icon name and the logical name of the icon, and how and where it is used.
Menus
Menus are lists of functions that can be displayed by user action. Menus can be invoked by the press of the Left softkey (Options menu) or by the Select key (OK options menu). The submenus can be described in the UI specication with the intended text style (see Appendix). The specication should describe: the function names and logical names in the menu, and the order of the functions in the menu; the function names and logical names of the submenus; when the functions are available, if they are context sensitive, and what they do.
Softkeys
Softkeys are located at the bottom of the screen. Their functions can change depending on the application state. A left softkey and right
120
softkey are available [see also the section the control pane for a description of the softkeys (Section 9.2)]. The specication should describe: labeling and logical names of the softkeys; when the softkeys are available and what they do.
Notes
Notes are messages that communicate temporary states of an application. Notes contain text, animation (optional), graphics (optional), and softkeys (optional); a sound can also be associated with a note. For a detailed description of the different types of notes see the section in notications (Section 11.4). The specication should describe: the note name and when the note is displayed; the type of the note (e.g. conrmation note, information note, warning note, error note, permanent note, wait and progress note); what string of text is displayed in the note and the logical name of the string; when the note disappears; what softkeys are displayed, their labels, and their logical names; details of whether there is a specic image, animation or sound associated with the note.
Queries
A query is a view where the user can submit information to the application. The information can be inserted into a text input box (data query), selected from a list (list query, multi-selection list query), or selected with the softkey (conrmation query). [For a detailed description of different types of queries, see Section 11.5; for different editor case modes (upper-case text/lower-case text/automatic/user selectable), and input modes (text/number), see Section 11.3.] The specication should describe: prompt text string of the query and the logical name of the string; whether the input line is automatically lled with text or is highlighted; the number of input lines used (in the data query); the number of characters that can be inserted (in the data query); the input mode of the query, text mode, or number mode; what softkeys are displayed, their labels, and their logical names.
USABILITY VERIFICATION
121
Logical Names
The logical name is a label or name of an element in the user interface, such as an icon or a text string. Logical names are used to help the translation of the application. The logical name strings can be composed of words that help to identify what the name signies (e.g. for the right softkey: <right softkey cancel>; for a note: <note waiting connection>).
6.6
Usability Verication
Almost every software product has been designed with ease of use as one of the design requirements. However, not all products are successful in terms of usability. Getting the usability of the nal product on the right level requires setting usability requirements and verifying them with usability verication tests. In the following sections we discuss the possibilities for setting and verifying the usability requirements of a software application. The setting of measurable requirements and the use of usability checklists are introduced. There is also a section on the possibilities to test usability at a sufciently early stage. Finally, a lead adapter test for the nal product is presented.
6.6.1
122
for comparing usability of competing products is introduced in the Section 6.6.2. After the user-needs study is completed, the target users and the main use cases for the product are dened. These data can be used for identifying user tasks related to the application and analyzing their criticality or frequency (Ruuska and V aa n anen, 2000). This information helps to set criteria on how efcient each task should be. Tasks under pressure are critical and should be able to be conducted with simple actions and without careful looking at the display. Tasks seldomly occurring may be placed deep in the Options menu.
USABILITY VERIFICATION
123
Table 6.2 describes different usability aspects, their denitions, checklists, and ways to measure the usability aspects. All usability requirements can be collected into one table that contains the denition of tasks, criticality, measurement, target criteria, verication plan, and verication results. The same table can serve as a requirement denition and verication plan and can provide information on verication results. The verication results can include how well the set targets have been reached and what kind of usability issues have been found. Table 6.3 gives an example of a usability requirements table for an image editor product.
6.6.2
Verifying Usability
The usability requirements are veried through usability evaluations. The usability verication plan should be part of the development project plan, so that resources and product increments can be allocated to the right time. The usability verication tests often reveal usability problems that should be corrected in the product. That is why it is recommended to start usability verication as early as possible, before it is too late to correct the errors without missing the planned launch date. The best way to verify usability is to organize usability tests with a sample of end users and predened test tasks, based on the verication plan. A group of 68 test users is usually sufcient to reveal all relevant usability issues and is signicant enough for verifying the usability, even if the number is not statistically signicant. Laboratory testing with videorecording equipment also allows accurate time measurements for analyzing the efciency of the tasks. In the absence of a usability lab, a normal meeting room can be used. Alternatively, the evaluation can also be conducted by external usability experts, who walk through the product with a usability checklist and identify possible usability problems. The person evaluating the usability or organizing the usability tests should preferably not be the designer of the product. The designers sometimes tend to be too subjective and love their design; which may affect the test situation. However, the designers and developers should participate in the test session by observing it, since it is an efcient way to wake them up if the product has usability problems. If the design team is small, the observers may sit in the same room and talk with the user about the design issues after the test is over (see Figure 6.13). The observation room can also be a separate room with a video monitor covering the test situation. The developers can also watch videorecordings of the session afterwards. The test results are updated in the usability requirements table for communicating the project management about the state of usability.
124
Usability aspects Denition Match between system and the real world Checklist The system should speak the users language, with words, phrases, and concepts familiar to the user, rather than system-oriented terms. Follow real-world conventions, making information appear in a natural and logical order. Accelerators (unseen by the novice user) may often speed up the interaction for the expert user in a way that the system can cater to both inexperienced and experienced users. They allow users to tailor frequent actions. They are important in often and routine tasks. Important in often and routine tasks. Design product for single-hand usage, use auditive and tangible feedback for interaction. There help users recognize, diagnose, and recover from errors. Error messages should be expressed in plain language (no codes), indicate precisely the problem, and constructively suggest a solution. Even better than a good error messages is a careful design that prevents a problem from occurring in the rst place Method of measurement Percentage of users who can conduct the task for the rst time without help.
Efciency
Number of key presses required to conduct the task Speed, related to competing products Number of provided shortcuts in routine tasks Percentage of tasks that can be conducted with a single hand Percentage of tasks that can be conducted without looking Number of errors Percentage of users that recover from errors without help
Mobility
Ability for users to use the product in mobile context of use. Error prevention and error messages
Error handling
USABILITY VERIFICATION
125
Learnability
Make objects, actions, and options visible. The user should not have to remember information from one part of the dialogue to another. Instructions for use of the system should be visible or easily retrievable whenever appropriate. The product guides the user to conduct the task. This is important in tasks used with occasional frequency
Percentage of users remembering how to do the task independently when they use it the second time after used or introduction.
Memorability
Users remember how to use it once they have been away from it for some time Help and documentation
Percentage of users to remember how to do the task independently after a period of time (week) since they have used the product Percentage of users to nd help from user documentation
Help
Even though it is better if the system can be used without documentation, it may be necessary to provide help and documentation. Any such information should be easy to search, focused on the users task, list concrete steps to be carried out, and not be too large. Users should not have to wonder whether words, situations, or actions in the user interface mean the same or different thing. Follow platform conventions.
Consistency
(continued overleaf )
126
(continued ) Denition User control and freedom Checklist Users often choose system functions by mistake, and will need a clearly marked emergency exit to leave the unwanted state without having to go through an extended dialogue. The device should support undo and redo The system should always keep users informed about what is going on, through appropriate feedback within reasonable time Dialogues should not contain information that is irrelevant or rarely needed. Every extra unit of information in a dialogue competes with the relevant units of information and diminishes their relative visibility Scale questionnaire after the evaluation (15): unpleasantpleasant boringentertaining uselessuseful (practically, socially) inefcientefcient uglybeautiful Method of measurement
Visibility
Aesthetic
USABILITY VERIFICATION
127
Table 6.3 Usability requirement table ID Task Frequencya Measurement Criteria Veried Result Usability issueb
1 2
3 2
100% of users can do it the second time 75% of users can enter and edit text to the image without help 100% of users can do it the second time Familiarity: 75% of users can add an icon to their image Satisfaction: All users can nd 20% of the provided icons useful Learnability: 100% of users can learn to do it Error handling: 100% of users understand what the cursor highlight or pointer indicates
Test 1 Test 1
Familiarity Satisfaction
Test 1
a b
128
Figure 6.13 Usability test setting: the observer follows the test via a video projector
The usability issues found can be categorized according to a checklist and rated based on a scale of criticality. If the set usability criteria are not met, the project management may require more design iterations, or they may decide to ease the criteria intentionally. Some of the issues found may cause a change request to the requirement specication or UI specication; these need to be handled in the change management of the project. It is also useful to write a test report with detailed ndings, correction proposals, and new design ideas. It serves as a future knowledge base for other projects.
USABILITY VERIFICATION
129
results are obtained when two products are compared; if three or more products are used, users tend to forget how each one worked. The test order should be changed between users, and the product brand should be hidden so as to avoid bias in the test results. The competing products must also be on a similar maturity level; if one product is a fully working end product and another is an unnished prototype, the end users will vote for the end product, no matter how good are the interaction and design of the prototype. If the comparison can be conducted before the product sales, possible usability problems of the product can be corrected if it falls behind the competitor in the test.
6.6.3
6.6.4
130
try out the product. A lead adapter test can give realistic information on how the actual product works in a real life situation before the product is sent to a larger audience. To guarantee a good user experience, it is better to have end-user contact with the product far earlier than this, but the company should not miss the opportunity to get good feedback and information in order to set usability requirements for the next product. Since the product is given to end users to test in real situations over a long period of time, users cannot be observed all the time and simultaneously. A good way to collect detailed, qualitative information is to ask the end users to keep a diary of their usage. With a wellplanned diary, the company gets information about how, when, and where the users use the product, the frequency of used functions, errors and problems, as well as improvement ideas. After the test period, the test users can be interviewed based on the diary notes. The diary helps the end users to remember even small details of events that occurred in the past. Often, those details are very relevant to the interests of the product team.
6.7 Summary
In this chapter User-centered design for Series 60 applications a practical process creating applications of high usability has been detailed. The process started from understanding end-user needs and continued with iterative design and evaluation cycles. The rst iterations are conducted in concept design workshops; later iterations are focused more on interaction design and UI details. We addressed the challenges of interaction design for smartphone user interfaces and described some useful guidelines for writing UI specications. We have also concentrated on various usability verication methods for assuring high-quality user experiences. Once application developers have addressed these issues of user experience design, they may focus on UI implementation issues, discussed, in the following chapters.
7
Testing Software
Testing means using and operating a system or a component in a specic environment, observing the results, and then evaluating the results of some aspect of the system or component (Binder, 1999, page 1113). The evaluation causes the test to be passed or failed, which is typically due to a aw in the tested item. Test plans, suites, and cases are designed with the aid of requirements, standards, and other development products, such as specications. Deviations or variations found in the development products during the testing of the software and investigation of the failures and failed test cases are called errors and defects. Software testing scope is usually categorized as follows: white box, the source code and internal details of the implementation are known and used; black box, only specications are used, but no internal details, in the testing. Unit and module testing are used as white box testing. Functional testing and system testing belong to black box testing. The scope of unit testing is a unit in a module; the scope of module testing is the whole module; the scope of functional testing is an implementation; and the scope of system testing is the whole system. The scope of integration testing is a little less clear, but usually its scope is testing the interoperations of an implementation in the whole system including hardware. In small systems, integration testing is seen as testing the interfaces of classes and modules in an application or implementation. Traditionally, these scopes are implemented and executed, one following the other, in time order, to form the test phases of a project. Every test phase has its own advantages compared with the others. Test phases are quite inefcient if they are executed in the incorrect phase of a project. Testing culture denes the exact to which terms are for white box and black box techniques and scopes. Whereas unit testing is highly code-dependent and verication is made at a very basic level (the unit is a class), functional testing is focused on features and implementation in an almost complete environment. Integration testing
132
TESTING SOFTWARE
tests the interoperability of the application or modules after integrating them into the system. System testing tests the system requirements and functionalities overall and also the volume, performance, and overload situations of the whole environment. The system testing task can also include building and integrating software into a complete environment. In testing, it is essential that everything is done systematically. The testing process proceeds in steps from test case design and planning, test execution, result validation and verication, and failure reporting to bug correction verication. These steps should be made in a systematic manner, so that every step can be reproduced later for a specic software build. Testing for a certain software build means that the results and the reports are valid only for that build. Especially in iterative software development, the need for regression testing is great and it is often done for every new build.
133
Project starts Requirements specification Implementation specification Architecture specification Development and inspections Module design Source code
Maintenance ready version Acceptance tests System and functional tests Integration tests Module tests Unit tests Testing and validation
Figure 7.1
veried against the specication than simply to read the test result, which is validated as incorrect. Even if the testing itself works ne, we need validation of the process, too. If testing is done, for example, in the environment, and has wrong, old, or faulty components, or components that have not been tested or updated, we easily get many failures. Testing can also be much harder to perform in such an environment. Because of a high number of failures, the need for regression testing is greater and thus takes more time. To be effective, testing should only be done on software and in an environment leads to that is valid for the test phase. This validation is implemented in the process by entry end exit criteria and can be dened in the test plans too. More about entry and exit criteria is found in Section 7.1.2.
7.1.1
134
TESTING SOFTWARE
need for stubs and other test drivers is bigger. Stub is a piece of code that has the same interface as the lower layers and possibly returns pre-determined values, but it does not contain code to performany real computations or data manipulations. Since the development and coding is done in slices, parts, and versions, the test should take account of changes made through the process to the nal tests. Also, it may be necessary to focus the testing goals on the ready parts of software only. In the process, it should be noticed that test execution can be nished and accepted only partly if some features are missing. Functional or system testing can rarely be done if integration is not ready. Test plans, test suites, and test cases are designed with the aid of software development specications, design les, requirements, and standards. Usually, different specications and design les are used as input for different test plans. Standards are available on test documentation (e.g. IEEE standard 829; See Binder, 1999, pages 34044). The test plan contains information about environment, responsibilities, schedule, and scope of testing. The test suite and cases contain detailed instructions for test execution and references to documentation used. The test case denes also the state of the implementation when starting the test, the test set up, inputs, conditions, procedures and the expected results. When the test suite and cases are executed, each test is evaluated as pass or no-pass. The test report contains the result of the test. The used environment depends a lot on the testing phase and the maturity of the system. Testing scopes, used documentation, and environment are, for example: unit and module testing: source code and design les, integrated development environment (IDE); integration: emulator environment (IDE), real environment, prototypes, interaction, and architecture design; functional testing: emulator environment (IDE), real environment, prototypes, requirements, functional and implementation specications, and standards; system testing: nal environment; customer acceptance testing: nal product. Used tools for testing are, for example: Debug asserts, invariants, and debugger; test drivers, stubs, and debug viewers (e.g. unit testing framework); test automation tools, test applications, console programs, emulator, and hardware.
135
Assertions should be used as built-in tests to indicate the defect directly. Assertion is a boolean expression, which is evaluated as true or false. Assertions can be used in a debug build, but they can be left to code for testing in real use and to prevent the execution of code in failure situations. For test personnel, assertion panics are easy to identify and report. See, for example, Nokia (2001b, 2001f). Section assertions provide more information on assertions. The debugger is used in integration, functional, and system testing for bug solving after the failure can be repeated securely. However, debugging itself does not belong to the testing activities.
7.1.2
7.1.3
Failure Corrections
How can one make a correction then? Usually, testing nds many deviations, which, of course, should be corrected. The failure rate depends greatly on the software and project in question. A new code usually has more defects than a recycled code. Failure management is essential in every software project and its value increases when the project scale gets bigger. For bug corrections, the test phases are iterative. The testing is done, reports are lled, failures are reported, and development gets back to
136
TESTING SOFTWARE
the V-model for the current correction to remove the defect. Then, the testing phases are executed again, but now also the corrections are veried. The tests for corrections can be added as new regression test cases. If the testing phases have already been accepted and the exit criteria are met, only a subset of the tests may be needed. Usually, the scope of regression testing is subjective and its denition is based on experience. It would be more secure to redo all tests in the regression testing.
SOURCES OF FAILURES
137
values of zero, and boundaries near to minimum and maximum values should be executed and tested at least once. In practice, a code that is not executed especially at its boundaries often fails in integration and functional testing. It is possible to use integration or functional testing only for these values, which are dened by equivalence partitioning. An equivalence class is a set of data or inputs, which are treated in the same way. Equivalence classes are usually stated in the specications (Perry, 2000 page 125). Most basic defects of this kind should preferably be caught at unit testing. Some values can, in fact, be difcult and troublesome to initialize in the working environment, and regression testing should be used in preference. The strategy for testing near or at equivalence classes and their boundary values is called partition testing (Binder, 1999, page 47). It is applicable for all testing scopes and integration.
7.2.3
Combinations
We get a little deeper into the internal design of the program when we use combinational logic. Again, we use boundary values in different sets. These sets are formed by, for instance, equivalence classes, and every set has its own features, which are implemented in different parts of a programs source code. An easy way to access these combinations is to list the values in a table and then choose the right values to test any set in the table. A common error is to write the source code without any limitations or conditions. These kinds of errors are usually found with one value of the erroneous set, so there is no need to use a full range of inputs in the testing. A decision table links inputs and their conditions to the correct actions or functions (Binder, 1999, page 12173). Conditions are evaluated as true or false. An action for a combination is selected, when all its conditions are true. With a decision table it is quite easy to nd errors in the combinational logic; for example, some inputs (or their combinations, if conditions exists) execute a wrong function, or some functions are unimplemented. A truth table is used to show all values for a Boolean function. It is like a decision table, but in a truth table, all values are represented as a truth value (e.g. true or false). In Table 7.1, a simple decision table for different speeds and bearer types is shown as an example. The action on the right-hand side of the table is to initialize the speed in implementation. In the implementation, the input range is partitioned to sets, which are processed by different actions. The initialized speed is not the same as the input value, because the implementation allows only a maximum speed of 28 800 bps
138
TESTING SOFTWARE Table 7.1 Decision table for right data the call speed initialization when the call type is analogue Call speed (bps)a Automatic 9 600 14 400 19 200 28 80056 700
a b
Call speed as an input (call type is analogue). Speed in implementaion. Note: CSD, circuit-switched data; HSCSD, high-speed circuit-switched data.
(bits per second). The input range also determines the bearer type, which is 9600 bps or 14 400 bps for circuit-switched data (CSD), and over 14 400 bps for high-speed circuit-switched data (HSCSD). In the table, it can be seen that inputs are partitioned by the call speeds to different bearer types (CSD and HSCSD), and the HSCSD speed rate is dened as 28 800 bps when the input speed is 28 800 bps or more for the analogue call type. The error case in the situation presented in Table 7.1 might be, for example, initializing a speed rate of over 28 800 bps in implementation. When equivalence partition testing and boundary values are used, at least six separate tests are needed to test the sets in Table 7.1. Depending on the implementation of the automatic speed initialization, even more tests are needed. In Table 7.1, the conditions for the input are done only for the input speed. The call type is analogue. If we want more conditions for the inputs, for example, by adding a condition for the call type (analogue or ISDN), the table size will increase (see Table 7.2) or we can make a separate table for the ISDN call type. The decision tables are applicable over the whole testing scope and development. In particular, the boundary values are easier to nd in the decision tables. In functional testing, decision tables can be valuable for designing test cases for special situations and checking the coverage of those test cases.
7.2.4
Memory Management
In memory management, and often in using a le system, pointers and handles are used exclusively. Null pointers and zero values and, of course, faulty cleaning are common sources of errors. Memory management and le system usage also have a physical limit. A defect in memory management can be hard to nd. Memory management failures usually do not give many clues to the situation, just that the data area is somehow corrupted and it may happen occasionally.
SOURCES OF FAILURES Table 7.2 Decision table for right data call-speed initialization; call type is analogue or ISDN Call speed (bps)a Automatic 9 600 14 400 19 200 28 80056 700 Automatic 9 600 14 400 19 200 28 800 38 400 43 20056 700
a b
139
Call typeb Analogue Analogue Analogue Analogue Analogue ISDN ISDN ISDN ISDN ISDN ISDN ISDN
Initialized bearer and call type Automatic CSD, analogue CSD, analoque HSCSD, analogue HSCSD, analogue CSD, ISDN v1.1 CSD, ISDN v1.1 CSD, ISDN v1.1 HSCSD, ISDN v1.1 HSCSD, ISDN v1.1 HSCSD, ISDN v1.1 HSCSD, ISDN v1.2
Initialized speed (bps)c Automatic 9 600 14 400 19 200 28 800 9 600 9 600 14 400 19 200 28 800 38 400 43 200
Call speed as an input. Call type as an input. c Initialized speed in implementation. Note: CSD, circuit-switched data; HSCSD, high-speed circuit-switched data.
In memory management, the correct testing phase for error situations is rst in white box testing (unit testing). The tests should at least provide an answer to the question regarding what to do when the memory allocation fails. Also, some receiving values are interesting. Maybe a pointer has not been updated, or there is a pointer to the memory allocation that is not in use anymore (especially when there is some failure or special situation in the function called). The Null value of a pointer should always be checked in case the call to the used interface fails. Trap harness, cleanup stack, and cleaning are used for better memory management and to indicate and prevent the execution of the faulty code. For a smartphone the memory resources are often insufcient. Outof-memory (OOM) situations should be tested for error recovery (see the unit testing example in Section 7.4). Also, the error recovery architecture for OOM errors may be complicated and so it is important to design it well.
7.2.5
140
TESTING SOFTWARE
When the used environment is a smartphone its most wanted feature is the ability to make and receive calls. At the system design level, all error situations should be designed in a way that no part of system can disturb the major feature (i.e. calling and receiving a call). Databases have features that should be considered at the system level. At the system level, the database design should answer to the following questions: What if the database is corrupted? What if the database is used simultaneously? Is the database efcient enough? How big can the database be? In system testing, performance and overload situations are usually tested, and, in a complete environment, multi-tasking is used. The Symbian OS environment offers the possibility of using traps, cleanup stacks, and cleaning in order to handle error situations. The trap harness mechanism offers the user at least some information about the error situation and prevents the faulty code being executed. Also, assertions can terminate the program when an error situation is detected. Termination should be used only when the code detects a programming error (should never happen situation), never runtime, or, especially, resource allocation failures. The failure of an assertion usually triggers program termination; the coding standards and inspections should enforce this. Memory and battery low messages, and other system messages to the applications are needed to prevent error situations, such as running out of memory. If these signals or messages are processed in advance, at least the user will receives a notication from the system, and he or she can react to the situation.
141
helper applications are used extensively. For the source code, there is a possibility of using analyzers (such as LeaveScan). A system of test tools, drivers, and software supporting test execution is sometimes called a test harness. Whereas integration and functional testing use tools not present in the software development environment, white box testing (unit and module testing) uses exactly the same IDE and software development kit (SDK) to build the unit testing environment, and the unit testing environment uses heavily the same source code to make an instrumented environment for testing. The test automation and scripting usually include their own development environment, with their own scripting or coding language and a possible executable environment (emulators and possible hardware). Also, differentiation tools should exist for test result analysis. When test automation and scripting is implemented correctly, great efciency is achieved in regression testing, because there is less reworking. Even if the test result verication is to be made manually, the automated test execution can save time; of course, the same skills are needed for testing as if it were done completely manually. Something that is easily forgotten is that test scripting and maintenance takes time; make sure that all benets and advantages are gained by using automation before starting test automation, even with the simplest goals.
7.3.1
Test Automation
Test automation covers all testing work. Test execution and result verication can be automated, and in some cases it is possible to generate inputs automatically. Usually, testing is only partly automated. For example, scripts are made manually, but tests are executed and the result is compared automatically with expected results veried in advance. In test automation, good results are achieved easily in regression and stress testing. In stress testing, the automated execution is done for long periods (hours and days), or a great amount of data is input, and it cannot usually be done manually. Unit and module testing are perhaps easier to automate than other testing phases. If unit testing uses executable test drivers and cases (code which implements the tests) it is possible to automate the execution and result validation. See the unit testing example in Section 7.4 in which the test cases are implemented as an executable code and results can automatically be validated during the execution of the test suite and a test report be generated. The goals for automating testing should be dened in advance. Automating the whole process can be very time-consuming and even
142
TESTING SOFTWARE
impossible, so the rst goal could be, for example, automating the test execution and checking the results manually. This is a much easier job and gives quicker results.
7.3.3 Comparison
For the comparison with expected results, a wide range of tools is available. If test execution results and output can be compared with expected results, the test status can be dened. A good comparison tool also offers masks for comparison, where the comparison is focused on certain conditions. For instance, the time and date stamps can be left out, the comparison criteria can be focused on strict lines or columns, and so on. Whenever the comparison fails, the comparison tool should be synchronized to continue the comparison. If the test environment and tool support writing logs that include information of the test status a simple search function is also applicable.
7.3.4 Debugger
Usually, the development environment includes a debugger for the execution of software. Debuggers are used for solving errors and nding defects. Debuggers usually have capabilities of showing the register and variable values and making breakpoints in the wanted code address or place in code. If the values of the variable can be changed, it can be used as a test-support tool by making test situations that otherwise would be hard to prepare. A debugger is a powerful tool for bug solving and also suits unit testing. The call stack usually points at the exact source of error, because
143
the call stack contains the stack of currently called code. The debug prints are used to generate the test results. A debugger can usually be used in all test driver environments; only some real time environments may be hard to debug.
7.3.5
Debug Output
When software is built with a special debug switch, the software built-in debug outputs can be read from the output viewer. Such a viewer can be part of the built-in environment or a special program. For example, the unit testing environment can use the debug output for outputting the test result. Here, debug output for CArrayTests unit tests in a unit testing environment is dened:
// define DEBUG_PRINT #ifdef _DEBUG /// Prints to debugger output #define DEBUG_PRINT RDebug::Print #else inline void EmptyDebugPrint(TRefByValue<const TDesC>, ...) { } #define DEBUG_PRINT EmptyDebugPrint #endif
The debug output is a clean way to print information on the internal state of the programs. Never use hard-coded test printings to the real user interface, because they might be forgotten to the source code and to the nal product. Also, when solving failures, debug prints can be used. Debug prints can be added, for example, to decision statements and, in this way, solve the path and values of variables, when a program has been executed. In a real time environment, this may be the only way to investigate the state of the program because use of a debugger may disturb and slow down the execution of the software.
7.3.6
Test Applications
Test applications are needed to create test input and possibly to validate the result. They are made by designers for testing the interfaces; there is no need to wait for all software to be integrated before testing. Test applications can also be used for performance evaluation in emulator and hardware environments. Symbian OS and Series 60 environments are provided with graphical user interfaces to be used in test environments before the nal user interface is ready.
144
TESTING SOFTWARE
For a test application it is possible to use the debug output printouts for displaying information on execution, and so the results can be veried more accurately. Test applications are not programs to be released, so the debug printouts can be used. The nature of the test application is between white box and black box testing; there are no limitations for using the code and program internal values, although the test application is used as a replacement for the real application or interface. When the whole system is not ready but the interfaces need to be tested in integration or functional testing, should we just wait? No, it is possible to use test applications to complement the unnished environment and make the integration bottom-up or top-down. Thus, testing, for example, is not dependent on the schedules of the rest of the project for integration, and we have the possibility of making a performance evaluation and bug corrections right away. When the real integration to hardware starts, we have a mature code ready, which answers questions of performance, usability, and for which the functions have been executed at least once. In the emulator environment it is possible to use the debugger and other source-code-dependent information, such as call stacks, in error situations. When preparation for integration or functional testing is done in the emulator environment with the aid of test applications, use of, for instance, a debugger in error situations is a great advantage.
UNIT TESTING
145
or unit testing and partly application testing) the tests themselves may be written in the source code. Almost all of the documentation of unit testing can be done at the source code level, and a failed test points the place of error directly. In the unit testing environment, for example, assertions can be used for testing the conditions. If a unit testing framework is used it usually has the ability to make result printouts, for example, to the console or to a debug window. As the unit tests are used to test the smallest parts of the software, testing by only the module interface (module testing) or user interface can be difcult. So, a test driver is required to execute and test the parts of a module (e.g. classes). Usually, a class itself is documented by, at the least, comments in the source code. The source codes internal logic (e.g. decision statements, classes) and its features are then tested. The focus in unit testing is: class construction and destruction; leaving, especially in out-of-memory situations; selection, decision, and iterative statements (in C++ these are, for example, if, else, switch, while, do, for, break, continue, return, and goto); execution paths of selection and decision statements; function calls, all arguments, and returning values; boundary, error, and null values; empty lists, a list with one item, and the rst and last items of the list. Appending a new element in an array is tested by initializing the array, appending the rst element, verifying that the element is really appended, and that the counter (if one exists) of the array is increased by one element. There is also a limit for the array, and the last element is also appended and, after that, appending a new element causes an error to happen. The error should be specied by a return value, for instance, and this value is then veried. In unit testing, the test stubs are also involved in the testing environment. Usually, the test stubs are used for initializing the test before the code under test is executed. They can also replace the interface and return, for example, the test values. Stubs are also used to simulate missing environment and libraries. Here, we come to an important situation: whenever unit testing is done and possible test stubs have been written, it is possible immediately to test the boundary and error values of the code. If unit testing is left out, we soon notice it in
146
TESTING SOFTWARE
functional testing and integration testing (bottom-up or top-down) as numerous errors in boundary areas. There are also problems in making test situations for error values and states. The required time for the integration or functional testing phase is increased along with the number of found failures, and the need for regression testing is thus greater. White box testing is very valuable when the boundary and error values, at least, are tested. The time required for correcting a wrong index, for instance, in coding phase is much shorter than in the integration testing phase.
UnitTestConsoleRunner.exe
UnitTest.dll
UnitTestDebugRunner.exe
TestCases.dll
Figure 7.2 Example of a unit testing environment and structure; DLL, dynamic link library
The rst step is to install the unit testing framework to the environment. After that, the framework is directly in use. The IDE debug window can be used for displaying the debug output and results. The next phase is to create a testing project, such as CArrayTests. In the example unit test, CArrayTests is used for basic unit testing of the Symbian and Series 60 template class CArrayFixFlat. It is surprising how easily index (boundary value) errors can appear when coding with the arrays. Test DLLs can be executed using the installed test drivers. The drivers are executed from the console with a driver (e.g. EUnitDebugRunner
UNIT TESTING
147
or EUnitConsoleRunner). When building is done for the udeb environment, in error situations (by means of a EUNIT ASSERT breakpoint), a debugger can be used. A demonstration for normal building procedure in the Series 60 environment is as follows:
bldmake bldfiles abld build wins udeb CArrayTests
7.4.2
Macros
For test cases, macros are used for writing the test case table and the test cases. Here, the EUNIT TESTCASE macro denes a test case. The test case table contains functions dened in the test suite:
// Test case table for CArrayTests EUNIT_BEGIN_TESTCASE_TABLE(CArrayTests, "CArrayTests test suite") EUNIT_TESTCASE("Test empty", SetupL, TestEmptyL, Teardown) EUNIT_TESTCASE("Test append", SetupL, TestAppendL, Teardown) EUNIT_TESTCASE("Test append and OOM", SetupL, TestAppendOutOfMemoryL, Teardown) EUNIT_TESTCASE("Test at", SetupL, TestAt, Teardown) EUNIT_TESTCASE("Test delete", SetupL, TestDeleteL, Teardown) EUNIT_TESTCASE("Test append KMaxElements", SetupL, TestMaxElementsL, Teardown) EUNIT_TESTCASE("Test at KMaxElements-1", SetupL, TestAtMax, Teardown) //EUNIT_TESTCASE("Test overflow", SetupL, TestOverflowL, Teardown) EUNIT_END_TESTCASE_TABLE
Every test case contains setup and teardown functions for test initialization. In the CArrayTests example, the tested class is instantiated in the setup and deleted in the teardown. In the example above, test cases dened by the EUNIT TESTCASE macro have output that gives the test name and other information to the user. In the macros, the functions used in test setup, executing the test, and nishing the test are dened.
7.4.3
Test Suite
A unit test suite for CArrayTests is derived from the unit testing framework. Now it is possible to add methods as test cases to class CArrayTests derived from the framework. Also, the iArray member variable is declared in the CArrayFixFlat template class. CArrayFixFlat is one of the used application interface classes in the Series 60 platfrom.
148
TESTING SOFTWARE
The CArrayTests unit tests do not implement all tests for CArrayFixFlat. Here, the unit tests are done for basic array manipulations and boundary values. For TestOverflow() causes the E32USER-CBase 21 panic to be raised, as Series 60 application programming interface (API) reference documentation species. In the examples, the basic idea of testing with boundary values and overows by using class and its functions can be seen. In the following test suite example, an iArray member variable is declared in the class CArrayFixFlat<TInt>. For simplicity, the type is TInt and the granularity is one. All test cases are declared as functions, which are then called when the whole test suite is executed. The test case implementation follows this example:
/* * CArrayTests test suite */ class CArrayTests : public CEUnitTestSuiteClass { public: static CArrayTests* NewLC(); public: ~CArrayTests() { delete iArray; } private: // Test case functions void SetupL(); void TestEmptyL(); void TestAppendL(); void TestAppendOutOfMemoryL(); void TestAt(); void TestDeleteL(); void TestMaxElementsL(); void TestAtMax(); void TestOverflowL(); void Teardown(); private: // Implementation EUNIT_DECLARE_TESTCASE_TABLE; private: // Data enum { KMaxElements=5, KGranularity=1, KTestValue=99 }; // Tested array is type of TInt CArrayFixFlat<TInt>* iArray; };
In the example above, the CArrayTests class is derived from the unit testing framework. The test suite contains the test cases as member
UNIT TESTING
149
functions in the class. The iArray is the pointer to the tested object. The EUNIT DECLARE TESTCASE TABLE then contains the test case table, which denes the member functions to be executed.
7.4.4
150
TESTING SOFTWARE
const TInt countBefore = iArray->Count(); __UHEAP_FAILNEXT(1); TRAPD(err, iArray->AppendL(value)); EUNIT_ASSERT(err == KErrNoMemory); EUNIT_ASSERT(iArray->Count() == countBefore); }
void CArrayTests::TestAt() { // Test value At() const TInt value = KTestValue; iArray->AppendL(value); EUNIT_ASSERT(value == iArray->At(iArray->Count()-1)); } void CArrayTests::TestDeleteL() // Index is starting from 0 { const TInt value = KTestValue; iArray->AppendL(value); iArray->Delete(0); EUNIT_ASSERT(iArray->Count()==0); } void CArrayTests::TestMaxElementsL() { // Append max count of elements // Index starts from 1 for (TInt i=1; i<=KMaxElements; i++) { iArray->AppendL(i); EUNIT_ASSERT( i == iArray->Count()); DEBUG_PRINT(_L(" CArrayTests: Testing KMaxElements, count is %d"),i); } } void CArrayTests::TestAtMax() { // Test value At(KMaxElements) for (TInt i=1; i<=KMaxElements; i++) { iArray->AppendL(i); } const TInt value = iArray->At(KMaxElements-1); EUNIT_ASSERT(value == KMaxElements); DEBUG_PRINT(_L(" CArrayTests: Value At(KMaxElements-1) = %d"), value); } void CArrayTests::TestOverflowL() { // Fill array to KMaxElements for (TInt i=1; i<=KMaxElements; i++) { iArray->AppendL(i); }
UNIT TESTING
// Append to max elements+1, use Insert // E32USER-CBase 21 panic is raised const TInt value = KTestValue; iArray->InsertL(KMaxElements+1, value); } void CArrayTests::Teardown() { delete iArray; iArray = 0; }
151
For automated execution of test cases, the test cases are implemented as functions in the source code. When the cases are executed, the unit testing framework is used to print a summary of the test results to the debug output. If assertion in the test case fails, a breakpoint is raised by the framework. Then, with the aid of the debugger, the reason for the failed execution can be solved. In the previous example, the test cases are implemented independently. So, every test case can be executed without disturbing the other test cases. The CArrayTests::SetupL() is used to initialize the class under test and then CArrayTests::Teardown() to delete it.
7.4.5
152
TESTING SOFTWARE
EUnitDebugRunner: "Test append KMaxElements" executed. EUnitDebugRunner: "Test at KMaxElements-1" Started CArrayTests: Value At(KMaxElements-1) = 5 EUnitDebugRunner: "Test at KMaxElements-1" executed. EUnitDebugRunner: "CArrayTests test suite" executed. EUnitDebugRunner: 7/7, 100% of tests succeeded. RemoveLibrary carraytests[1000af59]
In error cases, a breakpoint is raised to show the failed EUNIT ASSERT. So, the error can be investigated directly. Of course, some test cases cause a panic to be raised; in such a case, the call stack should be checked. The call stack contains the stack of the current function calls. An example of the call stack when a user breakpoint (failed assertion) is raised is given below; the assertion was modied to fail in the example to show the error situation:
TEUnitDebugAssertionFailureHandler::HandleAssertionFailureL(const TEUnitAssertionInfo & {...}) line 147 + 9 bytes EUnit::AssertionFailedL(const TEUnitAssertionInfo & {...}) line 19 CArrayTests::TestAppendL() line 114 + 75 bytes CEUnitTestSuiteClass::TTestCase::RunTestL() line 241 MEUnitTestCase::Run(MEUnitTestResult & {...}) line 56 + 47 bytes CEUnitTestSuiteClass::Run(MEUnitTestResult & {...}) line 148 CEUnitTestDll::Run(MEUnitTestResult & {...}) line 65 MainL() line 286 E32Main() line 310 + 29 bytes startupThread() line 211 + 5 bytes RunMainThread(void * 0x00402949 startupThread(void)) line 341 + 5 bytes User::StartThread(int (void *)* 0x5b001604 RunMainThread(void *), void * 0x00402949 startupThread(void)) line 438 + 7 bytes runThread(void * 0x008623e8) line 173 + 23 bytes KERNEL32! 77e8758a()
In the rst line of the call stack, it can be seen that the panic is caused by an assertion failure. In line 4, the call stack shows the function CArrayTests::TestAppendL(), where the panic occurred. Now, the developer can jump directly to the error situation in the debugger and, for example, investigate the value of the variables. After continuing execution of the test cases in the debugger from the breakpoint, the result in the debug output also contains the failed test case. In the next example, the whole execution result is presented:
AddLibrary carraytests[1000af59] EUnitDebugRunner: Running 7 tests EUnitDebugRunner: "CArrayTests test suite" Started EUnitDebugRunner: "Test empty" Started EUnitDebugRunner: "Test empty" executed. EUnitDebugRunner: "Test append" Started EUnitDebugRunner: "Test append": Assertion failure: (iArray-> At(iArray->Count()-1) != value), \SAMPLE\CARRAYTESTS\ Carraytests.cpp, line 114 ""
UNIT TESTING
EUnitDebugRunner: "Test append" executed. EUnitDebugRunner: "Test append and OOM" Started EUnitDebugRunner: "Test append and OOM" executed. EUnitDebugRunner: "Test at" Started EUnitDebugRunner: "Test at" executed. EUnitDebugRunner: "Test delete" Started EUnitDebugRunner: "Test delete" executed. EUnitDebugRunner: "Test append KMaxElements" Started CArrayTests: Testing KMaxElements, count is 1 CArrayTests: Testing KMaxElements, count is 2 CArrayTests: Testing KMaxElements, count is 3 CArrayTests: Testing KMaxElements, count is 4 CArrayTests: Testing KMaxElements, count is 5 EUnitDebugRunner: "Test append KMaxElements" executed. EUnitDebugRunner: "Test at KMaxElements-1" Started CArrayTests: Value At(KMaxElements-1) = 5 EUnitDebugRunner: "Test at KMaxElements-1" executed. EUnitDebugRunner: "CArrayTests test suite" executed. EUnitDebugRunner: 6/7, 85% of tests succeeded. RemoveLibrary carraytests[1000af59]
153
In the previous example, the failure of the test case test append was caused intentionally by a wrong assertion in line 7. The overow test is commented in the source test code as a panic is raised when it is executed. The failed test case results are also displayed. The result can be used directly in the test report. Lines 1721 and line 24 contain debug outputs which support and give more information on the test execution.
7.4.6
154
TESTING SOFTWARE
The other testing phases cannot test the internal design as well as unit testing can. For example, functional testing is focused on the whole implementation and its features. The correction of an error is also more time-consuming in the other testing phases and may not require any debugging.
APPLICATION TESTER
155
Figure 7.3
It also writes log les with memory information and timestamp, if a memory tracker DLL is used. These features make it quite effective for easy capture and script writing for stress tests. Test suites can be made and call to other test scripts is provided for modularity. AppTest can be used in hardware as well. The playback and, for instance, taking of screenshots are used as in the emulator environment.
7.5.1
DLL Command
Digia AppTest has verication support provided by a custom DLL interface. It makes it possible to extend the language for the exact verication purpose, and has complete custom DLLs for screenshots and memory-tracking commands. In the Series 60 GUI, it is quite hard to perform direct result verication automatically, but with a custom DLL this is possible. Of course, use of DLLs needs programming skills, but, in general, test drivers, stubs, and test applications that require programming skills have already been used before the functional testing phase. Use of DLLs in result verication makes the testing a little closer to unit testing (the term gray box may be used) and does not eliminate the need for test verication by the GUI. In practice, automated GUI content verication should be done by comparison, optical character recognition (OCR), text recognition, or by a GUI content support output (e.g. in plain text):
class MDLLInterface { public: virtual TInt Initialize( CScript* aScript, CLog* aLog ) = 0; virtual void Teardown() = 0;
156
TESTING SOFTWARE
virtual TBool StartL( CVariables* aArray, CCoeEnv* aCoeEnv ) = 0; virtual TBool EndL( CCoeEnv* aCoeEnv ) = 0; };
DLL command execution returns information on the execution of the DLL command. For return values, blocks are dened, for example, for failed situations. The DLL command has interfaces for starting, initializing, tearing down, and ending the command. The DLL is then called from the script with a DLL tag.
APPLICATION TESTER
157
A test suite is used to collect many individual scripts together. With smaller subscripts, the script maintenance is much easier. The subscripts are used to make a library for test suites and so to make modular test suites. In the example above, the included subscripts contain captured input for replaying the execution. The subscripts are designed in a way that all views of the application are checked, and then the subscripts return to the main view. The execution can be looped. With this script, the application is smoke tested and the execution can be made for a long period (e.g. one day), or the amount of used data can be large. The advantages of automated smoke and stress tests are that they are easy to do and they can be executed often, even when there is no time to test manually. Manual test may not even nd those errors that can be detected by executing stress tests. The script les contain the captured and possibly modied information and commands in application tester scripting language. A part of the captured events script le is as follows:
<BODY> <NAME>PbkTest01</NAME> <AUTHOR>Its me</AUTHOR> <DESCRIPTION>Phonebook views</DESCRIPTION> <DATE>04.06.2002 01:02</DATE> <MAIN> <APP name="PHONEBOOK.app"> <KEYDOWN interval="1.58">EStdKeyLeftFunc</KEYDOWN> <KEYDOWN interval="0.48">EStdKeyDevice0</KEYDOWN> <KEY interval="0.00">EKeyDevice0</KEY> <KEYUP interval="0.05">EStdKeyDevice0</KEYUP> <KEYUP interval="0.04">EStdKeyLeftFunc</KEYUP> <KEYDOWN interval="0.86">EStdKeyLeftFunc</KEYDOWN> <KEYDOWN interval="0.17">EStdKeyDevice0</KEYDOWN> <KEY interval="0.00">EKeyDevice0</KEY> <KEYUP interval="0.08">EStdKeyDevice0</KEYUP> <KEYUP interval="0.02">EStdKeyLeftFunc</KEYUP> <KEYDOWN interval="1.23">EStdKeyRightArrow</KEYDOWN> <KEY interval="0.00">EKeyRightArrow</KEY> <KEYUP interval="0.13">EStdKeyRightArrow</KEYUP> <KEYDOWN interval="1.28">EStdKeyLeftArrow</KEYDOWN> <KEY interval="0.00">EKeyLeftArrow</KEY> <KEYUP interval="0.00">EStdKeyLeftArrow</KEYUP> <KEYDOWN interval="1.01">EStdKeyLeftFunc</KEYDOWN> <KEYDOWN interval="0.25">EStdKeyDevice1</KEYDOWN> <KEY interval="0.00">EKeyDevice1</KEY> <KEYUP interval="0.06">EStdKeyDevice1</KEYUP> <KEYUP interval="0.03">EStdKeyLeftFunc</KEYUP> </APP> </MAIN> </BODY>
The timestamp is seen in this sample. There is a possibility of using timing when doing the playback. On left of the script there
158
TESTING SOFTWARE
are timestamps (intervals) that are used for timing the playback. The captured events are used to open and view an entry in the Phonebook. For example, in the emulator environment, pressing key c causes the following events to be captured:
<KEYDOWN interval="0.47">C</KEYDOWN> <KEY interval="0.00">c</KEY> <KEYUP interval="0.09">C</KEYUP>
Events can be read and written in plain text, and the captured input can be used directly for playback. For clarity, the capture and playback script les should be used in small subscripts for modular design of the tests. App Test is capable of catching leaves:
<BODY> <NAME>Phonebook</NAME> <AUTHOR>Its me</AUTHOR> <DESCRIPTION></DESCRIPTION> <DATE>21.05.2002 12:43</DATE> <MAIN> <APP name="PHONEBOOK.app"> </APP> <APP name="PHONEBOOK.app"> <OOM type="EDeterministic" rate="50"> <KEYDOWN interval="2.02">EStdKeyLeftFunc</KEYDOWN> <KEYDOWN interval="0.40">EStdKeyDevice0</KEYDOWN> (...Here are the captured events) <KEYDOWN interval="0.55">EStdKeyDevice1</KEYDOWN> <KEY interval="0.00">EKeyDevice1</KEY> <KEYUP interval="0.04">EStdKeyDevice1</KEYUP> <KEYUP interval="0.04">EStdKeyLeftFunc</KEYUP> </OOM> </APP> </MAIN> <EXCEPTION type="Leave"> <NOTE>Leave.. ${value}</NOTE> </EXCEPTION> </BODY>
With an exception tag, it is possible to dene that, for example, a leave is caught. This is very convenient in OOM error situations, for instance, because execution of the script can be continued after OOM. Usually, the OOM error note is displayed by the system to the user, as in Figure 7.4. The OOM rate value can be initialized in the loop, and so the OOM test coverage can be created. The OOM errors are used to test the capability of the application to handle memory allocation failures.
APPLICATION TESTER
159
When an OOM error happens, the exception can be displayed to the user by a note. In this example (Figure 7.5), the application does not show the OOM error note when the AppTest is active, since instead of the systems OOM error note, the AppTests exception block is called. A note Leave.. 4 is displayed to the user. It is important that the OOM error can be caught, and the memory tests can continue. The global error value (4) means KErrNoMemory in the Series 60 and Symbian environment. In the following example, the memory consumption of the application is investigated during execution. In line 9, the memory tracker DLL is started. The memory tracking is done at one-second intervals, and the log is written to a le MemScan.log. The used subscript
160
TESTING SOFTWARE
in this example is PbkTest02, which opens and views one entry in the Phonebook:
<BODY> <NAME>Phonebook</NAME> <AUTHOR>Its me</AUTHOR> <DESCRIPTION></DESCRIPTION> <DATE>21.05.2002 12:43</DATE> <MAIN> <APP name="PHONEBOOK.app"> </APP> <DLL interval="1.0" dll="MemTrackerDLL.Dll" app="phonebook.app" log="c:\MemScan.log"> <APP name="PHONEBOOK.app"> <INCLUDE name="c:\documents\Pbk\PbkTest02.txt"/> </APP> </DLL> </MAIN> </BODY>
Memory tracker is one of the extension DDLs provided with Digia AppTest. With the memory tracker it is possible to track the memory consumption of the application in some time interval. The memory tracker makes a log le, where the memory consumption and heap size are displayed:
Tracking application "phonebook.app" 04th Jun 2002 12:58:10.98 AM Bytes allocated = 65216, Heap size = 85892, Available = 4236, Cells allocated = 1337 04th Jun 2002 12:58:12.14 AM Bytes allocated = 93584, Heap size = 122756, Available = 6648, Cells allocated = 1839 04th Jun 2002 12:58:13.24 AM Bytes allocated = 93584, Heap size = 122756, Available = 6648, Cells allocated = 1839 04th Jun 2002 12:58:14.35 AM Bytes allocated = 93584, Heap size = 122756, Available = 6648, Cells allocated = 1839 04th Jun 2002 12:58:15.45 AM Bytes allocated = 93584, Heap size = 122756, Available = 6648, Cells allocated = 1839 04th Jun 2002 12:58:16.55 AM Bytes allocated = 97828, Heap size = 122756, Available = 1612, Cells allocated = 1907 04th Jun 2002 12:58:17.65 AM Bytes allocated = 97828, Heap size = 122756, Available = 1612, Cells allocated = 1907
The log le contains information on the execution. The timestamp and used memory are displayed. The memory consumption can be monitored for long periods and it can be useful in optimization of the application, for example. In the memory tracker log, for example, increasing memory consumption can be detected.
SUMMARY
161
Usually, complete automation is impossible, and this should be notied when starting to make scripts for the testing. It is wise to start with the simplest possible goals. In smoke and stress testing, capture and replay capability can be sufcient to make the scripts if the execution can be looped. AppTest is suitable for the following situations: smoke tests, stress tests, functional test support in initialization and setup, out-of-memory tests of an application, functional testing, when the result verication is done by DLLs or manually. Scripting all the tests is difcult, because the maintenance work can increase during the project. Scripts should be modular, and subscripts should be used. When the application or program changes, for example, by the user interface it is necessary only to modify that subscript. Digia AppTest provides DLL extension support. If the result verication can be made by a DLL it is possible to automatize the functional tests too. Sometimes, the term grey box is used in this testing situation.
7.6
Summary
Although testing should be systematic work, it needs not be uninteresting. When the schedule is tight and there are many instructions in the process there is also room for creativity. As in software development, testing needs skill and creativity for good results to be obtained. Experimentation is more than allowed, especially in unit testing. Although testing nds nasty-sounding things, such as errors, during the project, and shows that something does not work, it should be remembered that, nally, all tests should be passed and the testing results should be accepted. This means that the program, too, has reached an acceptable quality and it is conrmed that it does what is required. To nd and correct an error is not enough, since we know that every error correction should be veried, and every change in the software can be a place for a new defect. Testing as a process should be modied for the current software project, and it should be developed during and afterwards. If some process ts the application development, it may not t a low-level device driver implementation. Also, the scale of the project can be a challenge.
162
TESTING SOFTWARE
When starting a software project one should also dene how the testing should be done. This includes, for example: the testing techniques and methods; the testing process and the way the testing is implemented in the project; responsibilities; error database and change management; documentation, test plans, suites, and cases; the version control system; testing tools and environment. Testing skills may also include development capability. In iterative software development there is a need for a testing environment where the environment is capable of executing software from almost the starting phase of the project. This increases the need for test support software (e.g. test drivers, stubs, and applications) and, of course, the need to develop them.
Part 2
Graphics, Audio, and User Interfaces
8
Application Framework
The benets of separating a graphical user interface (GUI) application into an engine part and user interface (UI) part were discussed in several chapters in Part 1 of this book. The application engine, also known as an application model, contains all data of the application and the structures and algorithms dealing with it. The engine is responsible for interacting with the system devices, such as the le system, communications, etc. The application user interface, usually called simply the application in Symbian OS, has two main tasks: it deals with the visual representation of the application data on the screen (picked up from the engine), and it sets the overall behavior of the application, dening how the users interact with the application. This chapter provides a description of the Uikon application framework, in addition to its Avkon extension. Uikon provides the application launching service, a set of standard UI components and user input handlers for the applications. Avkon provides the concrete look-and-feel for UI components and new UI components for smartphones based on the Series 60 Platform. The other chapters in Part 2 describe the use of Avkon UI components in the applications.
8.1
166
APPLICATION FRAMEWORK
Uikon extension (Avkon) Adaptable core (Standar Eikon) Lode and feel
Core (Uikon)
Graphics
System
and standard GUI components (also known as controls) with basic look and feel for all Uikon applications. An adaptable core (standard Eikon) is implemented by the provider of the UI style. In the case of the Series 60 Platform, standard Eikon has been implemented by Nokia. Together with a style-dependent framework extension (Avkon), standard Eikon provides the style-dependent set of UI components with their own look and feel. In Figure 8.2, the contents of the Uikon framework is depicted in more detail. Application architecture (App Arc) and control environment (CONE) provide a great deal of UI functionality in a general and an abstract form. Uikon makes the UI functionality concrete. In addition, Uikon supplies the look and feel for the standard UI components. The Uikon and CONE frameworks have virtual functions through which the rest of Symbian OS can be reused. Application developers derive classes implementing these virtual functions with any specic functionality required. Writing GUI applications involves a great deal of derivation from the base classes of Uikon and CONE. The role of the CONE in event handling and graphics drawing will be described later in this chapter (Section 8.3.2). The basic classes of any GUI application are shown on the left-hand side of Figure 8.3. Sometimes, applications may require a separate controller object, if the engine provides asynchronous services, taking a long time to execute, for example. The controller is added to the set of basic classes on the right-hand side of Figure 8.3. If a separate controller is not required, the AppUI (CMyAppUi) also contains the controllers functionality. The application class (CMyApplication) is used in the launching of the application. The document class creates the application user interface. In addition, it provides a layer between
167
Application
Uikon Application architecture (App Arc) Control environment (CONE) Window server Stream store File server Font and bitmap server
GDI
Kernel
Figure 8.2
CMyApplication 1 1 CMyModel
CMyApplication 1
CMyDocument 1 1 CMyModel
CMyAppUi 1 1 CMyController
CMyView
168
APPLICATION FRAMEWORK
the user interface, the model, and the le in le-based applications. The commands invoked by the user are handled in the AppUI class. The view class (CMyView) displays the users data on the screen. Note that there is not a base class for engine (CMyModel) in the application framework. The engine can be derived, for example, directly from CBase, which is the base class of any compound class, or CActive, which is the base class of active objects.
CONE CCoeControl
Figure 8.4 Uikon application classes; App Arc, application architecture; CONE, control environment
Application
The application class is derived from CEikApplication, which is derived from a class declared by the application architecture. There are two functions to be implemented in this class, CreateDocumentL(), which creates the applications document, and AppDllUid(), which identies the application by returning its unique identier. The declaration of the application class of the rockpaperscissors (RPS) game is as follows:
// INCLUDES #include <eikapp.h> // CONSTANTS // UID of the application const TUid KUidRPSGame = { 0x101F5BBD };
169
AppDllUid() returns the unique identier (UID) number (0x101F5BBD) and CreateDocumentL() uses documents NewL() factory function to create a document. Note that a pointer to the application class is passed to the document. The document needs the UID value from the application class when handling application les.
170
APPLICATION FRAMEWORK
Document
The document class is derived from CEikDocument, which is derived from a class in the application architecture. The document class instantiates the application engine (model) and creates the AppUI object using the CreateAppUiL() function. The TryLoadDataWrittenByMsgViewerL() function is used to read any existing message data (i.e. moves from a le) if another player has challenged this player earlier.
// INCLUDES #include <eikdoc.h> // CONSTANTS // FORWARD DECLARATIONS class CEikAppUi; class CRPSGameAppUi; class CRpsMessage; class CRpsModel; // CLASS DECLARATION /** * CRPSGameDocument application class. */ class CRPSGameDocument : public CEikDocument { public: // Constructors and destructor /** * Two-phased constructor. */ static CRPSGameDocument* NewL(CEikApplication& aApp); /** * Destructor. */ virtual ~CRPSGameDocument(); public: // New functions CRpsModel& Model(); protected: // New functions /** * Checks, if there is a received message. Reads it, if it * exists. Otherwise starts a new game. */ void TryLoadDataWrittenByMsgViewerL(); private: // from CEikDocument /** * From CEikDocument, create CRPSGameAppUi "App UI" object. */ CEikAppUi* CreateAppUiL(); private: CRPSGameDocument( CEikApplication& aApp ); void ConstructL(); private: CRpsModel* iModel; };
171
In addition to the model and application UI creation, the document stores (and restores) the applications data, including the user data and application settings, such as the selected language of the application. All ling operations are also performed from the document. Data is stored using a stream store, which is built on top of the le server. Stream store denes services for adding and deleting streams to a store. A stream is a sequence of any binary data, representing, for example, the state of the object, and a store is a collection of streams. The base class for the document (CEikDocument) has two functions for storing and restoring the state of the application: StoreL() and RestoreL(). The functions have an empty implementation and must be implemented by the developer who wishes to persist application data. To avoid unnecessary storing in cases where document data have not been changed, SaveL() can be used. The document has a ag indicating whether its content has changed or not. This ag may be set by using a SetChanged() function and get using a HasChanged() function, respectively. SaveL() calls StoreL() only if HasChanged() returns ETrue. A complicated application may require several streams to store its state. First, document data are stored. Documents StoreL() calls ExternalizeL() in the model, which may further call the Externalize() function of the components. We saw the opposite in Chapter 5. The document asked the model to read message data by calling its AddDataFromReceivedMsgL() function, which called Internalize() rst from the CRpsMessage class and then from the CRpsMoves class. Each stored (or restored) stream is identied by an identication number (ID). In a store, the rst stream is a dictionary stream, containing the IDs of all the streams it contains. The individual streams are accessed in the store, using the dictionary stream. The implementation of the document class of the RPS game is shown below. We have omitted constructor and destructor functions because of their simplicity and TryLoadDataWrittenByMsgViewerL(), because it has already been shown in Chapter 5 (page 91). After the creation of the model, the document checks rst if there is a new message received. Application user interface is created in a standard way using two-phase construction:
// INCLUDE FILES #include "RPSGameDocument.h" #include "RPSGameAppUi.h" #include "RpsModel.h" // ================= MEMBER FUNCTIONS ======================= void CRPSGameDocument::ConstructL()
172
APPLICATION FRAMEWORK
{ iModel = CRpsModel::NewL(); TryLoadDataWrittenByMsgViewerL(); }
AppUI
The AppUI class is derived from CEikAppUI, which is derived from the base class in the CONE (CCoeAppUi). The main task of this class is to handle application-wide UI details. Responses to various kinds of events can be handled at the AppUI level by implementing virtual functions of the base class. The functions are not purely virtual, but their implementation is empty. Virtual functions to be implemented are: HandleKeyEvent(), which is called if a key press event occurs (and all the controls on the control stack return EKeyWasNotConsumed from the OfferKeyEventL() function); we will come back to event handling in Section 8.3.2; HandleForegroundEventL(), which handles changes in keyboard focus when an application is switched to the foreground or from the foreground; HandleSwitchOnEventL(), which handles an event, when the smartphone is switched on; HandleSystemEventL(), which handles events generated from the Window server; HandleMessageReadyL(), which handles the message ready message generated by the Window server; HandeApplicationSpecificEventL(), which handles any application-specic events; this function is called when the framework has an event ID beyond the range of Window server events; HandleCommandL(), which is called when the user issues commands; this may be the only function that is implemented from the event handling functions. The AppUI class also takes care of creating application views. The views are created in the ConstructL() function. In the RPS game, the application UI class is derived from Avkon extension, and we will show the code in later examples in this chapter (see Section 8.1.2).
173
View
The application view is derived from the CONE control class (CCoeControl) or any class for which the base class is CCoeControl. All controls need to draw themselves (unless they are simply containers having controls). Thus, they have to implement a virtual Draw() function, dened in CCoeControl. The Draw() function receives a parameter, which is a reference to TRect object generated by the windows server. The object contains the smallest bounding box to need redrawing. TRect classes represent rectangles, the sides of which are parallel to the axes of the coordinate system.
8.1.2
CAknApplication
Avkon
CAknDocument
CAknAppUi
CONE CCoeControl
Figure 8.5 Avkon application classes; App Arc, application architecture; CONE, control environment
174
APPLICATION FRAMEWORK
reduce the derivation chain, but it could have been made to be sub class of the CAknApplication as well.
Avkon AppUI
The CAknAppUi class provides color scheme support and look and feel for all generic controls. It also provides a few new accessories specic to the Series 60 Platform: status pane: located on the top part of the screen, this displays status information on the current application and state as well as general information on the device status (the signal strength and battery charging); the status pane may be invisible; command button array (CBA): located at the bottom of the screen, this shows the text associated with softkeys. In addition, there is a functionality for handling system events in general and, for example, HandleForegroundEventL() implementation. There is another AppUI base class (in addition to CAknAppUi) in the Series 60 Platform: CAknViewAppUi. This class is used, if view classes are derived from the CAknView base class rather than from CCoeControl. The Series 60 view architecture uses these classes as well, as we will describe in Chapter 13. The header le of the application UI class is shown below. The KMsgBioUidRpsMessage constant denes the RPS game smart message type. The other constant, KNumberOfMoves, denes how many moves must be selected before a challenge can be created or a challenge can be responded to TRpsGameState denes the states of a simple state machine. We have used just one variable (iState) to indicate the state-dependent behavior instead of applying a state design pattern. The initial state is EStateNull, which is changed to EStateChallenge or EStateNewGame, depending on whether the player has received a new challenge or not. When a response message has been received, the state is changed to EStateResponse. DoChallengeL() checks if the player has made enough selections, after which it calls SendChallengeMsgL() to send the message. The SendChallengeMsgL() function uses the engines communications services to send a message, or it sends it directly using the CSendAppUi class, which creates a message and uses the message framework to send the message to the other player. DoPlayL() redraws the view and calls CheckWinnerL() to calculate the score for each player. The InformationNoteL() function shows the result of the game as a note (see Chapter 11). Finally, DynInitMenuPaneL() is called just before a menu is opened. This
175
function determines, which menu items are available in the menu, based on the state of the game. For example, the challenge cannot be sent before a minimum number of moves has been selected. Note that the view created by the application user interface is CRPSGameContainer, indicating that there are several views in the container:
// INCLUDES #include <eikapp.h> #include <eikdoc.h> #include <e32std.h> #include <coeccntx.h> #include <aknappui.h> // FORWARD DECLARATIONS class CRPSGameContainer; class CRPSGameDocument; class CRichText; class CSendAppUi; // CONSTANTS const TUid KMsgBioUidRpsMessage = {0x0FFFFFFB}; const TInt KNumberOfMoves = 3; _LIT(KLose, "You lose!"); _LIT(KWin, "You won!"); _LIT(KDraw, "Its a draw!"); // CLASS DECLARATION /** * Application UI class. * Provides support for the following features: * - Eikon control architecture * - view architecture * - status pane * */ class CRPSGameAppUi : public CAknAppUi { public: enum TRpsGameState { EStateNull, EStateNewGame, EStateChallenge, EStateResponse }; // // Constructors and destructor /** * EPOC default constructor. */ void ConstructL(); /** * Destructor. */ CRPSGameAppUi();
176
APPLICATION FRAMEWORK
public: // New functions void SetState( TRpsGameState aState ); public: // Functions from base classes private: // From MEikMenuObserver void DynInitMenuPaneL( TInt aMenuId, CEikMenuPane* aMenuPane ); private: /** * From CEikAppUi, takes care of command handling. * @param aCommand command to be handled */ void HandleCommandL( TInt aCommand ); /** * From CEikAppUi, handles key events. * @param aKeyEvent Event to handled. * @param aType Type of the key event. * @return Response code (EKeyWasConsumed, EKeyWasNotConsumed). */ TKeyResponse HandleKeyEventL( const TKeyEvent& aKeyEvent, TEventCode aType ); private: /** * Challenges another player (no challenge message received) */ void DoChallengeL(); /** * Sends the challenge message e.g. in the smart message */ void SendChallengeMsgL(); /** * Checks the result of the game * received and at least KNumberOfMoves made. */ void DoPlayL(); void CheckWinnerL(); /** * Tells the winner in the UI. */ void InformationNoteL( const TDesC& aText ) const; CRPSGameDocument& Document() const; private: //Data CRPSGameContainer* iAppContainer; CSendAppUi* iSendAppUi; TRpsGameState iState; };
Avkon View
CAppView may be derived from CAknView or from CCoeControl or any of its subclasses. CAknView is not a control. It is not derived from CCoeControl, but directly from CBase. Although it is not a control, it is still a CONE view. When using objects instantiated from
177
CAknView-derived classes, we typically dene a CCoeControlderived container with no or a trivial Draw() method. The container then consists of all the visible controls. In the RPS game, we have not derived our view class from CAknView but rather from CCoeControl, as shown in the header le:
// INCLUDES #include <aknview.h> // CONSTANTS const TInt KMaxNumOfItems = 3; _LIT(KImagePath, "z:\\system\\apps\\rpsgame\\rpsimages.mbm"); // FORWARD DECLARATIONS class CEikLabel; // for example labels class CRpsMoves; // CLASS DECLARATION enum TRpsContainerState { ESelecting, EPlaying }; /** * CRPSGameContainer container control class. * */ class CRPSGameContainer : public CCoeControl, MCoeControlObserver { public: // Constructors and destructor /** * EPOC default constructor. * @param aRect Frame rectangle for container. */ void ConstructL(const TRect& aRect); /** * Destructor. */ ~CRPSGameContainer(); public: // New functions /** * State setting function. */ void SetState( TRpsContainerState aState ); /** * @return KNumberOfMoves */ TInt MaxCount() const; /** * Adds a new move to selected set of moves. */ void AddCurrentToSelectedItemsL(); /**
178
APPLICATION FRAMEWORK
* @return the selected moves */ const CRpsMoves& MyItems() const; void UndoLastItem(); void SetMyItemsL( const CRpsMoves& aMoves ); void SetOpponentItemsL( const CRpsMoves& aMoves ); public: // Functions from base classes TKeyResponse OfferKeyEventL(const TKeyEvent& aKeyEvent, TEventCode aType); private: // from CCoeControl void SizeChanged(); TInt CountComponentControls() const; CCoeControl* ComponentControl( TInt aIndex ) const; void Draw( const TRect& aRect ) const; void HandleControlEventL( CCoeControl* aControl, TCoeEvent aEventType ); private: // new functions void LoadImagesL( const TDesC& aImageFile ); void ShowNextItem(); void ShowPreviousItem(); private: //data CArrayPtrFlat<CFbsBitmap>* iBitmaps; TInt iCurrentItemId; CRpsMoves* iMyItems; CRpsMoves* iOpponentItems; TRpsContainerState iState; TInt iMyItemIndex; TInt iOpponentItemIndex; };
KMaxNumOfItems represents the number of moves that must be drawn on the screen. Also, the container class has states to restrict possible functionality. In the ESelecting state the player does not yet have enough moves to make a challenge (or to check the result). When the minimum number of required moves has been reached, the state is changed to EPlaying. The AddCurrentToSelectedItemsL() function adds a new move to a set of moves and redraws the screen. MyItems() returns the move set, and UndoLastItem() removes the last move from the set of moves. SetMyItemsL() and SetOpponenItemsL() set the set of moves according to the data read from the message. The moves are drawn on the screen using the function PlayNextMyItem() and PlayNextOpponentItem(). The function of LoadImagesL() is simply to load the rock, paper, and scissors bitmaps from les. Functions overridden from CCoeControl will be described later in this Chapter 8.3.1.
LAUNCHING AN APPLICATION
179
8.2
Launching an Application
The application is started by selecting it from the shell. The shell gets the name of the application and puts it into a CApaCommandLine. After that, the shell creates a new process, passing apprun.exe (part of Eikon) as the name of the executable to run in the new process. Apprun.exe calls the EikDll::RunAppInsideThread() static function, which creates CEikonEnv environment. RunAppInsideThread() calls the CEikonEnv::ConstructAppFromCommandLineL() function, which loads the dynamic linh library (DLL; actually, it calls a function in the application architecture to do this). ConstructAppFromCommandLineL() calls NewApplication(), which creates a new application process. The implementation of NewApplication() is as follows:
// =============================== OTHER EXPORTED FUNCTIONS // // --------------------------------------------------------// NewApplication() // Constructs CRPSGameApp // Returns: CApaDocument*: created application object // --------------------------------------------------------// EXPORT_C CApaApplication* NewApplication() { return new CRPSGameApp; } // --------------------------------------------------------// E32Dll(TDllReason) // Entry point function for EPOC Apps // Returns: KErrNone: No error // --------------------------------------------------------// GLDEF_C TInt E32Dll( TDllReason ) { return KErrNone; }
The application creates the document. The CreateAppUiL() function in the document class is called by ConstructAppFromCommandLineL(). The AppUI takes care of creating application views. Finally, RunAppInsideThread() calls the CCoeEnv::ExecuteD() function, which starts the active scheduler that runs the event loop waiting for the user input. Note that new(ELeave) is not used in NewApplication() function and thus NewApplication() is not a leaving function. The framework checks whether the return value of the constructor is
180
APPLICATION FRAMEWORK
different from null to check the success of object creation. E32Dll() is required by all libraries. In our case, it does nothing.
181
182
APPLICATION FRAMEWORK
else if ( iState == EStateChallenge ) { aMenuPane->SetItemDimmed( ERpsGameCmdChallenge, ETrue ); // Are there any items selected? if ( iAppContainer->MyItems().Count() == 0 ) { // No selected items -> No use for Undo command aMenuPane->SetItemDimmed( ERpsGameCmdUndo, ETrue ); // Dont allow challenge command. aMenuPane->SetItemDimmed( ERpsGameCmdPlay, ETrue ); } // Are there enough items selected? if ( iAppContainer->MyItems().Count() < iAppContainer->MaxCount() ) { // Dont allow challenge command. aMenuPane->SetItemDimmed( ERpsGameCmdPlay, ETrue ); } break; } else if ( iState == EStateResponse ) { aMenuPane->SetItemDimmed( ERpsGameCmdUndo, ETrue ); aMenuPane->SetItemDimmed( ERpsGameCmdChallenge, ETrue ); } break; } default: { break; } } }
This function is called by the Uikon framework just before a menu pane (CEikMenuPane) is displayed. The default implementation of the function is empty. The developer may override the function to set the state of menu items dynamically according to the state of the application data. CEikMenuPane is a control derived from CCoeControl. We have used its SetItemDimmed() function so that menu items, are not shown that are not available to the user. The dimmed menu items are identied by commands associated with menu items in the resource le. We will show examples of command denition soon. In the Series 60 Platform, dimmed menu items are not shown at all. In other UI styles, items may be just dimmed or grayed out. We have only one menu in the RPS game identied by the R_RPSGAME_OPTIONSMENU ID in the resource le. In case of a new game, for example, it is not possible to choose challenge or play commands. Commands available in separate states are shown in Figure 8.6.
183
Figure 8.6 Menu items available in separate states of the rockpaperscissors game: new game (left), challenge (middle), and response (right)
Resource les are text les used in dening UI components. In Symbian OS, resource les dene binary data and text resources only. Use of resource les has three advantages: applications are smaller, because it is more efcient to describe UI components in resource les and component behavior in code; localization is easier, because it is not necessary to walk through the whole source code; it is easier to port applications to a new target, because resource les are separate from application binary. Resource le denition in the Series 60 Platform can contain a status pane, CBA buttons, menu and menu panes, dialogs, and strings. The rst denition in the le is NAME, which is up to a four-character-long name of the resource les. The name allows one application to use several resource les. The Uikon as well as Avkon resource le has to begin with three standard resources: RSS_SIGNATURE, TBUF, and EIK_APP_INFO. The signature is left blank. A buffer may be empty as well or it can be used to dene a le name that the document class uses. EIK_APP_INFO species the resources that dene the UI components, as shown below:
// RESOURCE IDENTIFIER NAME RPSG // 4 letter ID // INCLUDES <eikon.rh> <eikon.mbg> <avkon.rsg> <avkon.rh> <avkon.mbg> "rpsgame.hrh"
184
#include "rpsgame.loc" #include "eikon.rsg" //
APPLICATION FRAMEWORK
RESOURCE DEFINITIONS
RESOURCE RSS_SIGNATURE { } RESOURCE TBUF { buf="RPSGame"; } RESOURCE EIK_APP_INFO { menubar = r_rpsgame_menubar; cba = R_AVKON_SOFTKEYS_OPTIONS_BACK; } //---------------------------------------------------// // r_rpsgame_menubar // STRUCT MENU_BAR // { // STRUCT titles[]; // MENU_BAR_ITEMs // LLINK extension=0; // } // //---------------------------------------------------// RESOURCE MENU_BAR r_rpsgame_menubar { titles= { MENU_TITLE { menu_pane = r_rpsgame_optionsmenu; } }; } //---------------------------------------------------// // r_rpsgame_menu // STRUCT MENU_PANE // { // STRUCT items[]; // MENU_ITEMs // LLINK extension=0; // } // //---------------------------------------------------// RESOURCE MENU_PANE r_rpsgame_optionsmenu { items= { MENU_ITEM { command = ERpsGameCmdUndo; txt="Undo"; }, MENU_ITEM { command = ERpsGameCmdChallenge; txt="Challenge"; }, MENU_ITEM { command = ERpsGameCmdPlay; txt="Play"; }, MENU_ITEM { command = EEikCmdExit; txt="Exit"; } }; } RESOURCE TBUF r_info_msg_challenging { buf="Challenging!"; } RESOURCE TBUF r_info_msg_not_enough_moves { buf="Not enough moves!"; }
185
There are several kind of les that can be included in the resource le. Files having an extension .rsg are generated resource les. When resources are compiled, there are two output le types. The other is a compiled binary le used by the application in the run time, whereas the other is a generated le used when the application is compiled. For example, avkon.rsg contains identiers for Avkon resources such as R_AVKON_SOFTKEYS_OPTIONS_BACK. Files with an extension .rh contain resource denitions in the form of resource structures. Commands are enumerated in the les having an extension .hrh. Finally, it is possible to include ordinary .h les and .loc les. The latter le types contain string denitions in the form of #define statements, which are included in the resource le. All resources are dened in the same way: keyword RESOURCE, name of the resource structure, and resource name. For example, RESOURCE MENU_BAR r_rpsgame_menubar denes the only menubar of the RPS game. The EIK_APP_INFO structure is dened in uikon.rh and is as follows:
STRUCT EIK_APP_INFO { LLINK hotkeys=0; LLINK menubar=0; LLINK toolbar=0; LLINK toolband=0; LLINK cba=0; LLINK status_pane=0; }
We have dened only menubar and CBA in the RPS game, but there are a few other possible resource denitions as well. The CBA denes names of the softkeys. R_AVKON_SOFTKEYS_OPTIONS_BACK denes that the left softkey is labeled as Options, and the right one as Back. One of the Options combinations should be used. These enable the menu to be shown automatically when the left softkey is pressed. The menu item resource structure denition is as follows:
STRUCT MENU_ITEM { LONG command=0; LLINK cascade=0; LONG flags=0; LTEXT txt; LTEXT extratxt=""; LTEXT bmpfile=""; WORD bmpid=0xffff; WORD bmpmask=0xffff; LLINK extension=0; }
186
APPLICATION FRAMEWORK
The command is dened in an .hrh le. A menu item can have other menu items if it is cascaded. Flags may specify, for example, whether there is an item separator between menu items. Txt denes the text label shown in the menu item in the user interface. It is also possible to use bitmaps in menu items in addition to text. Refer to Nokia (2001f) on avkon.rh and uikon.rh for a complete description of resource les. Commands are enumerated in an .hrh le as in the example below:
enum TRPSGameMenuCommands { ERpsGameCmdUndo = 0x06000, ERpsGameCmdChallenge, ERpsGameCmdPlay, ERpsGameSelect };
Note that you should start the enumeration from 0x6000, not to get confused with Uikon and Avkon commands. Commands are handled by the HandleCommandL() function, explained in the next section.
Command Handling
Commands associated with menu items are handled in the HandleCommandL() function. Note that the system shuts down the application by sending a command EEikCmdExit. That is why it should be handled in the HandleCommand() function, although not used by the application. Its implementation is quite simple, as seen below:
void CRPSGameAppUi::HandleCommandL(TInt aCommand) { switch ( aCommand ) { case EAknSoftkeyBack: case EEikCmdExit: { Exit(); break; } case ERpsGameSelect: { iAppContainer->AddCurrentToSelectedItemsL(); break; } case ERpsGameCmdChallenge: { DoChallengeL(); break; }
USER INTERFACE OF THE ROCKPAPERSCISSORS GAME case ERpsGameCmdPlay: { DoPlayL(); break; } case ERpsGameCmdUndo: { iAppContainer->UndoLastItem(); break; } default: break; } }
187
A specic function is called with respect to the command dened in the .hrh le and provided by the framework. This function implements the basic interactions with the user. Below, we show just the implementation of DoPlay(). Other functions are rather straightforward to implement. DoPlay() sets the state, redraws the view, and calls CheckWinnerL() to calculate the nal results of the game. CheckWinnerL() goes through opponents and players moves, move by move, and calculates the score according to the following rules: the rock beats the scissors, the scissors beat the paper, and the paper beats the rock. The nal result is given as a note to the user:
void CRPSGameAppUi::DoPlayL() { iAppContainer->SetState( EPlaying ); iAppContainer->DrawNow(); CheckWinnerL(); } void CRPSGameAppUi::CheckWinnerL() { TInt myScore(0); TInt opScore(0); if ( iState == EStateChallenge ) { // Challenge message contains the opponent moves and // my moves are in container. const CRpsMoves& myMoves = iAppContainer->MyItems(); const CRpsMoves& opMoves = Document().Model().ChallengeMoves(); for ( TInt i = 0; i < myMoves.Count(); i++ ) { if ( myMoves.Move( i ) > opMoves.Move( i )) { myScore++; } if ( myMoves.Move( i ) < opMoves.Move( i )) { opScore++; } else
188
{ // Draw }
APPLICATION FRAMEWORK
} } else if ( iState == EStateResponse ) { // Other way around. const CRpsMoves& opMoves = Document().Model().ResponseMoves(); const CRpsMoves& myMoves = Document().Model().ChallengeMoves(); for( TInt i = 0; i < myMoves.Count(); i++ ) { if( myMoves.Move( i ) > opMoves.Move( i )) { myScore++; } if( myMoves.Move( i ) < opMoves.Move( i )) { opScore++; } else { // Draw } } } if( opScore > myScore ) { InformationNoteL(KLoose); } else if( opScore < myScore ) { InformationNoteL(KWin); } else { InformationNoteL(KDraw); } }
Notes
Notes are dialogs, that may disappear automatically without user interaction. There are several note types in the Series 60 Platform, as we will see in Chapter 11. In the RPS game we have used CAknInformationNote to tell whether the player has won or lost the game or whether the nal result was a draw. Note how easy it is to use notes. The developer has to provide text to be notied as a descriptor. The note object has to be created, and ExecuteLD() shows the object on the screen, after which it deletes the object:
void CRPSGameAppUi::InformationNoteL( const TDesC& aText ) const { CAknInformationNote* note = new (ELeave) CAknInformationNote; note->ExecuteLD( aText ); }
189
8.3.2
LoadImagesL( KImagePath );
SetRect(aRect); ActivateL(); }
First, we have dened this control to be window-owning. Actually, this has to be, because this is the only control of the application. Window-owning controls call the CreateWindowL() function, which creates a new child window in the applications window group. After creating the window, other objects are created. This includes a bitmap array for paper, rock, and scissors bitmaps. SetRect() sets the extent (position and size) of the control with respect to the rectangle area provided by the application UI class. ActivateL() sets the control ready to be drawn. The Draw() function draws the control. It is also used in redrawing, although it is never called from the application. The framework takes care of calling this function. In case of a redraw, the Window server species an invalid area to be redrawn as a parameter to the Draw() function. The function may then determine which part of it must actually be redrawn, if any.
190
APPLICATION FRAMEWORK
Before any drawing, we must get the graphics context. This is a local copy of the system graphics context. Modications are rst done to the local context and then ushed to the Window server taking care of changes on the screen. In the Draw() function of the RPS game, there is not much more than bitmap drawing, as shown in the example code below:
void CRPSGameContainer::Draw(const TRect& /*aRect*/) const { CWindowGc& gc = SystemGc(); gc.SetPenStyle(CGraphicsContext::ENullPen); gc.SetBrushColor(KRgbWhite); gc.SetBrushStyle(CGraphicsContext::ESolidBrush); gc.DrawRect(Rect()); // Draw the selected images if( iState == ESelecting ) { TSize selectedImageSize( 30, 20 ); TPoint selectedImageTopLeft( 5, 10 ); for(TInt i = 0; i < iMyItems->Count(); i++) { TRect rect( selectedImageTopLeft, selectedImageSize ); TInt imageType = iMyItems->Move( i ); gc.DrawBitmap( rect, iBitmaps->At( imageType ) ); selectedImageTopLeft+=TPoint( selectedImageSize.iWidth+5, 0 ); } // Draw the big image TSize imageSize( 90, 60 ); TRect clientRect = Rect(); TPoint topLeft( (clientRect.Width() - imageSize.iWidth)/2, 80 ); TRect rect( topLeft, imageSize ); gc.DrawBitmap( rect, iBitmaps->At( iCurrentItemId ) ); } else { TSize imageSize( 30, 20 ); TPoint myImageTopLeft( 5, 10 ); TPoint opponentImageTopLeft( 5, 50 ); TPoint horizontalAddition( imageSize.iWidth+5, 0 ); // Draw my items. for(TInt i = 0; i < iMyItems->Count(); i++) { TRect rect( myImageTopLeft, imageSize ); TInt imageType = iMyItems->Move( i ); gc.DrawBitmap( rect, iBitmaps->At( imageType ) ); myImageTopLeft+=horizontalAddition; } // Draw opponent items. for(TInt j = 0; j < iOpponentItems->Count(); j++) { TRect rect( opponentImageTopLeft, imageSize ); TInt imageType = iOpponentItems->Move( j );
191
ENullPen pen style denes that the pen is not used for drawing. The brush is used to draw the background of the application white. Bitamps are drawn with DrawBitmap(), to which the bitmap location and bitmap le names are given. The selectable item is drawn in the bottom middle of the screen. The use of xed values such as here is not very good programming. They make, for example, the porting to different UI styles with their own screen resolution difcult. Selected items are shown at the top left of the screen, below which the response (or challenge) moves are drawn, as shown in Figure 8.7.
Event Handling
The CONE environment implements an event loop for handling UI events. The framework automatically creates a session to the Window server from which the events are received. The events may be key-press events, pointer-down or pointer up events (if the smartphone supports a pointer), redraw events or events from other controls. The Window server takes care of drawing to the window using the Font and bitmap server and the graphics device interface (GDI). The OfferKeyEventL() function below is used for key event handling. It is more complicated than the handling of pointer events, because we know the position where a pointer event occurred. The
192
APPLICATION FRAMEWORK
event is easily delivered to the right control according to the coordinates, but there are no coordinates for key events. In our application this does not cause problems, because we have only one control, which should be responsible for handling any key events:
TKeyResponse CRPSGameContainer::OfferKeyEventL( const TKeyEvent& aKeyEvent, TEventCode /* aType*/ ) { switch( aKeyEvent.iCode ) { case EKeyLeftArrow: break; case EKeyRightArrow: break; case EKeyUpArrow: { ShowNextItem(); return EKeyWasConsumed; } break; case EKeyDownArrow: { ShowPreviousItem(); return EKeyWasConsumed; } break; case EKeyDevice3: { AddCurrentToSelectedItemsL(); return EKeyWasConsumed; break; } default: return EKeyWasNotConsumed; break; } return EKeyWasNotConsumed; }
In general, controls are added into a control stack, when the controls are constructed. A key event from the Window server is received by the window group in the foreground (i.e. the active application). The CONE framework goes through all the controls of the application in the control stack and offers them the event. If the control is added to the stack and it has an implementation of the OfferKeyEventL() function, it is capable of processing key events. The return value of this function indicates what happened to the event in the function. If the control is not expecting any key events it does nothing and returns EKeyWasNotConsumed. In this case, the CONE framework continues
SUMMARY
193
offering the key event to another control in the stack until one is found, which returns EKeyWasConsumed. We have dened interaction for three key events. Items may be browsed by up and down arrows of the navigation key and the item can be selected with EKeyDevice3, which corresponds the selection made to the navigation key. The whole RPS game is available at www.digia.com/books. This chapter and Chapter 5 contain a description of almost every function in the example.
8.4
Summary
The application framework denes a set of base classes from which developers derive their own classes to be used in applications. The base classes of the framework enable the reuse of OS services in a straightforward way. The Uikon framework denes abstract application classes for application creation, UI component drawing, and event handling. In the Series 60 Platform, Avkon is an extension library for the Uikon framework, which provides a concrete look and feel for Uikon GUI classes. In this chapter we presented a description of the basic base classes for an application: CAknApplication, CAknDocument, CAknAppUi, CAknViewAppUi, and CAknView. The last two functions are not used in the RPS game example but they plan an important role in view switching, described in Chapter 13. We showed which functions to implement in a minimal GUI application having very simple eventhandling requirements. In the following chapters we will go through all the GUI components that can be used in applications. So far, we have used only menus and notes.
9
Standard Panes and Application Windows
In the Series 60 Platform, the term screen corresponds to the entire pixel area of the physical screen. Windows are components of the screen. One window may ll up the entire screen or a part of it, leaving other parts visible. Each application runs in its own window. Panes are subcomponents of windows and are sometimes called subwindows as well. One window may contain many panes, and each pane may contain subpanes, and so on. The Application window is the main window, which lls up the entire screen. The application window acts as a parent for the various panes. Typically, an application window owns three panes: status pane, main pane, and control pane. In this chapter we describe the panes and their usage. We show how to get the whole screen area for the application if that is required. We also explain the structure of panes and application windows having these panes.
195
(a)
(b)
Figure 9.1 Status pane with (a) normal layout and (b) idle layout
The status pane has two different layouts: a normal layout with the signal, context, title, navigation, and universal indicator panes (Figure 9.1a); the idle state layout with the signal, context, title, navigation, battery, and the universal indicator pane, observe here that the universal indicator pane has switched to a sideways orientation and now reveals the hidden battery pane (Figure 9.1b). Only some of the status pane controls are local to the application. Some general device state indication controls are present on a system server. Thus the CEikStatusPane is a client-side view of some of the controls in the status pane. An application has a status pane instance that is created by the application user interface framework upon the application construction. The layout of the status pane is read from the resource les. This stub hooks up with the server-side status pane; its function is to synchronize the server status pane controls with the client. A reference to the status pane can be acquired through the environment. The CAknAppUi, CAknViewAppUi, and CAknView classes have a StatusPane() function that can be used to retrieve a handle to the applications status pane instance. In AppUi this is a public function, so when you are not deriving from any of the above classes, you can get the handle through the CEikonEnv::Static(); for example, by calling:
CEikStatusPane* statusPane = iAvkonAppUi->StatusPane();
or
CEikStatusPane* statusPane = iEikonEnv->AppUiFactory()->StatusPane();
The status pane is divided into local-application-owned controls and global-server-owned controls. Applications can interact only with the subpanes they own through the application programming interface (API). Server-side panes can be accessed through the Avkon notier
196
client/server API. The local application owned status pane controls are the: title pane context pane navigation pane The local default implementations can be replaced with custom controls. These controls are all derived from CCoeControl. The server owned controls are: battery pane signal pane indicator pane idle layout context pane Only selected applications have access to the server-side objects through the notier API. Retrieving a certain status pane control is done by calling the ControlL() function with the status pane identication number ID as a parameter. This call returns a CCoeControl that has to be cast into the wanted control; for example, retrieving the navigation pane:
iNaviPane = STATIC_CAST<CAknNavigationControlContainer*> (StatusPane()->ControlL(TUid::Uid(EEikStatusPaneUidNavi)));
In order to be safe when calling this function, it is recommended to ask the pane capabilities whether the required pane is present:
if (statusPane && statusPane->PaneCapabilities(paneUid).IsPresent()) { return statusPane->ControlL(paneUid); }
197
Figure 9.2
Title pane
name taken from the application information le (AIF). The title pain is shown in Figure 9.2. The text can be set, retrieved, and reset to the default value. When the text is set, a copy of it is made and the ownership of the descriptor remains with the client application. There is also a version that does not leave and takes ownership of the descriptor. In some situations, this can be more than useful for example, when we have to restore the previous title pane text in the destructor of a class. Retrieving the text from the title pane does not transfer ownership or the descriptor, so you have to take a copy of it if you need it after assigning a new title. Pictures can be set from bitmaps and Symbian OS bitmap les. Alternatively, the context of the pane can be set from a resource structure. If the resource structure contains both a text and an image, the text is shown primarily:
RESOURCE TITLE_PANE r_my_title_pane { txt = "Hello world!"; }
Most of the time the title pane will contain the application name or a descriptive text about the current view. The text is primarily shown in a large one line font; when a longer text is required an automatic switch to a smaller font is made. In case this is still not enough, two lines are used; after that, the text is truncated from the end.
9.1.2
Context Pane
The context pane shown in Figure 9.3 is used to show the application icon and, in idle state, the clock. The CAknContextPane control is the default implementation, which is capable of setting, getting, and swapping bitmaps in the control. When set, the context pane always takes ownership of the image. The context pane default control shows the application icon from the AIF le. Restoring the default does not access the AIF an optimization that is very useful. The context pane owns a copy of the default application AIF icon. Swapping the image takes ownership of the new picture but returns ownership of the old image. The resource structure is the most
198
common way to set the context pane. Here we are using a platform bitmap from the system .mbm le:
RESOURCE CONTEXT_PANE r_my_context_pane { bmpfile = "z:\\system\\data\\avkon.mbm"; bmpid = EMbmAvkonQgn_menu_unknown_cxt; bmpmask = EMbmAvkonQgn_menu_unknown_cxt_mask; }
Figure 9.4
The navigation pane can be decorated with the appropriate control. The decorator control container contains the decorated controls. The status pane returns a CAknNavigationControlContainer object
199
that is a stack of controls. These controls are pushed on top of the navigation pane stack and are then automatically drawn. Then, again, when popped, the pane below is drawn. An exception to normal stack behavior is the editor indicators, that have higher priority. They are always shown if they exist on the stack. Any control pushed when an editor indicator is on the stack is inserted right below the indicator control. Also, when the same control is pushed again on the stack it is moved to the topmost position of the stack, so the stack never contains multiple instances of a control. A control is popped from the stack by deleting it. When there is an editor indicator on the stack and the stack is popped, the topmost non-editor indicator control is popped. If you want to remove a certain non-topmost control from the stack you must use a pop that takes a reference to the decorator; this can be used to remove editor indicator from the stack. The CAknNavigationControlContainer class contains factory functions for creating the various types of decorators. The navigation decorator can also be created from resources using the NAVI DECORATOR structure. This resource structure contains the type that is contained in the structure. For example, if the decorated control is an ENaviDecoratorControlTabGroup the structure that is read is a TAB GROUP:
RESOURCE NAVI_DECORATOR r_my_navi_decorator { type = ENaviDecoratorControlTabGroup; control = TAB_GROUP { tab_width = EAknTabWidthWithOneTab; active = 0; tabs = { TAB { id = EMyAppMainViewId; txt = "Main view"; } }; }; }
The control container does not own the contained controls. Therefore, the programmer is responsible for deleting the controls. To prevent icker, it is recommended that you rst add the new decorator and then delete the old.
Tabs
Tabs can be used to show that there are different types of views from the available data. Example of four navigation tabs in the navigation
200
pane is presented in Figure 9.5. The tabs are created in the navigation pane by rst using the factory function in CAknNavigationControlContainer to create a tab group. This can be done either from resources or from code. A tab group is a collection of tabs. Here a tab group is created from a resource structure:
iCoeEnv->CreateResourceReaderLC(resReader, R_MY_TAB_GROUP); iNaviDeco = naviPane->CreateTabGroupL(resReader);
The resource structure that is loaded is a TAB GROUP and contains information on the conguration of the tab group. The width of the tab group selects the number of tabs shown simultaneously. The index in the tab group of the active tab is followed by a list of TAB structures that describe the individual tabs:
RESOURCE TAB_GROUP r_my_tab_group { tab_width = EAknTabWidthWithOneTab; active = 0; tabs = { TAB { id = EMyMainListViewId; } }; }
The factory function returns a CAknNavigationDecorator object that decorates the contained CAknTabGroup object. To reach the contained object, you must cast the return value of the function that returns the contained object to CAknTabGroup:
CAknTabGroup* tabGroup = static_cast<CAknTabGroup*> (NaviDeco->DecoratedControl());
Now you can add tabs to the group. They are added in order from left to right.
201
A tab can contain a bitmap or text. The most common way to add tabs is from resource les, but you can also create them using the bitmaps or text factory functions. Each tab is associated with a tab ID and has a certain index in the tab group. Using the tab ID you can replace or delete a specic tab. Setting the currently active tab can be done using the tab ID or its index in the group. There are various layouts for tabs: two, three, four small tabs, and three long tabs. The three long tabs are stacked on top of each other so that one is visible. The other layouts have the tabs fully visible. If there are more than four tabs in the tab group they are not all shown but can be navigated to by showing the navigation arrow. In general, applications should not have dynamic tabs or more than six tabs; If these are shown, it will confuse the user and make application navigation difcult (Nokia, 2001g). The CAknNavigationDecorator class has the navigation arrows that are used to show the user that there are tabs available in the equivalent direction. These can be made visible, hidden, highlighted, or dimmed with the corresponding functions. First we must make the arrows visible by calling
iNaviDecorator->MakeScrollButtonVisible(ETrue);
Navigation Label
The navigation label can be used when there is a very large number of similar items to be browsed by scrolling horizontally between views. An example of a navigation pane containing a text label is shown in Figure 9.6. The construction is similar to that of tabs in the way that there is a factory function in CAknNavigationControlContainer that creates a decorator that contains a CAknNaviLabel object. The resource structure used for the resource-loaded version is NAVI LABEL, containing the text for the label:
RESOURCE NAVI_LABEL r_my_navigation_label { txt = "Hello world!"; }
This provides setting and retrieval of the text in the navigation label. The factory function in the control container can be used to set a default text.
202
Figure 9.6
Navigation Image
An image can be set on the navigation pane. This decorator-contained image is a CEikImage that is constructed from a bitmap and its masked with the factory function in CAknNavigationControlContainer. Also, a resource le factory function is available. This uses the NAVI IMAGE structure. The architecture is similar to the one described in connection with tabs:
RESOURCE NAVI_IMAGE r_my_navigation_image { bmpfile = "z:\\system\\data\\avkon.mbm"; bmpid = EMbmAvkonQgn_indi_attach_audio; bmpmask = EMbmAvkonQgn_indi_attach_audio_mask; }
Indicators
The navigation pane can be used to show various indicators. The CAknNavigationControlContainer can create a volume indicator and editor indicator decorators. An example of navigation pane containing an editor indicator is shown in Figure 9.7. The volume indicator is constructed from a resource structure. The CAknVolumeControl class use left and right arrow keys for the volume adjustment. The behavior of the CAknNavigationControlContainer toward editor indicators was discussed at the beginning of this section on the navigation pane. They always have the highest priority on the control stack. Thus, any other non-editor indicator
Figure 9.7
203
control that is pushed is not the topmost control on the stack. The control that is decorated in the navigation pane control container is CAknIndicatorContainer. From there we can set the message length indicator and adjust its state. Only the front end processor (FEP) is supposed to alter the editor indicators. The responsibility of the FEP is to keep track of the current editor and its input mode and to adjust the editor indicators accordingly. The FEP owns the control container editor indicators. If the application has to set its own editor indicators to the pane, a reference to the editor indicator container can be acquired, when the focus is on the editor, by calling
iAvkonEnv->EditingStateIndicator()->IndicatorContainer().
Custom Controls
To make a custom navigation pane control you can use NewL in CAknNavigationDecorator to decorate your custom control. This takes a reference to the CAknNavigationControlContainer and a CCoeControl-derived control that is decorated for the container. Now you can push your own control on the navigation pane.
Empty
The navigation pane can also be left empty by the application. It is easiest to do this by pushing an empty control on the navigation control container stack. An empty navigation pane is shown in Figure 9.8.
9.1.4
Signal Pane
The signal pane shown in Figure 9.9 is a server-side status pane control. There is only a single instance of this object at any time in the device. Only system applications can communicate with this, through the RNotifier. The interface to this can be found in the notify servers AknNotifier interface. It communicates with the
204
Eikon notify servers AknNotifier plug-in. The Eikon notier server forwards its state changes to the signal control.
205
Figure 9.10
Currently, there is no way for third-party developers to add their own controls. The class used is CAknSmallIndicator; it does not have a public API but contains a notice/promise of the upcoming feature to add ones own indicators. The system application handles the small indicator by creating one with the wanted indicator ID as parameter:
iEnvelopeInd = CAknSmallIndicator::NewL(KAknSmallIndicatorEnvelopeUid);
The possible indicator states are EAknIndicatorStateOff, EAknIndicatorStateOn, and EAknIndicatorStateAnimate. After use, it is deleted.
9.1.6
Full-screen Mode
In some cases you might wish to use the whole screen for your application as shown in Figure 9.11 (e.g. for games and certain types of viewers). The status pane can be hidden, but you have to be very careful that if a leave occurs the status pane is restored. The system does not take care of this for you. You can use the cleanup stack with a TCleanupItem. This is achieved by calling the status pane class MakeVisible function. For example:
206
CONTROL PANE
207
without a text and a command ID. An example control pane with Ok and Cancel softkeys is shown in Figure 9.12. If the suitable softkey combination is not available in the platform you will have to make your own softkeys. The button array contains two CBA BUTTON structures; the rst will be the left softkey, and the second the right softkey:
RESOURCE CBA r_softkeys_ok_cancel { buttons = { CBA_BUTTON { id = ESoftKeyOK; txt = "OK"; }, CBA_BUTTON { id = ESoftKeyCancel; txt = "Cancel"; } }; }
Either button structure can be left empty to indicate an empty softkey. The softkeys can be changed using the handle retrieved through the CAknView classes Cba() function. The CEikButtonGroupContainer has functions to control the softkey buttons. For example, new softkeys can be set using
Cba()->SetCommandSetL(R_AVKON_SOFTKEYS_OPTIONS_EXIT);
In a dialog, the CBA can be retrieved through the CEikDialog class ButtonGroupContainer() function.
9.2.2
Scroll Indicator
Traditionally, the scroll indicators are shown at the sides on the window, as shown in Figure 9.13. In the Series 60 Platform, the vertical scroll indicator is on the control pane.
When a component that needs a scroll indicator is constructed, it creates an instance of CEikScollBarFrame. Using the Object provider mechanism, the client code must ensure that a suitable CBA
208
is made known to the object provider so that the control will get the correct CBA. The component does not create its own local scrollbars.
and SetContainerWindowL() automatically. So, what is left for the programmer is to set the top-level control or view. These must set the application user interface or view as their object provider. These know the CBA and the menu bar, so a handle can be acquired. This is achieved by calling the
SetMopParent(MObjectProvider* aParent)
of the control. The object-provider mechanism can be used to provide objects to subobjects, or, more generally parent to child controls. All that is needed is to override the MopSupplyObject (TTypeUid aId). The ID corresponds to the requested object. If the control corresponds to the requested ID, the object should be returned by calling return aId.MakePtr(object), otherwise return TTypeUid::Null(). This way, the subcontrols request forwards all the way to the object that can provide the requested control. The objects that need to be provided are CEikButtonGroupContainer, CEikCba, and CEikMenuBar. In Eikmop.h there is a utility function that helps to return any of these. The ID of the object provided is declared in the header with the DECLARE TYPE ID macro. To access an object though the object provider, you need to call the T* MopGetObject(T*& aPtr) function in the MObjectProviderderived class. The requested object reference is set in the pointer, passed to the function.
SUMMARY
209
9.3
Main Pane
The main pane is the principal area of the screen where an application can display its data. The main pane can be used freely by the applications to draw whatever needed. In that case, the responsibility of the look and feel rests on the applications designer. However, the main pane will usually include one of a number of standard components: list: there are several standard list types to choose from; list types are described in Chapter 10; grid: there are several types available; see Chapger 10; nd pane: this is used together with a list, allowing the user to search list items alphabetically; status indicators: there are present only in the idle state, immediately below the navi pane, displaying status indicators; few indicators appear also in the universal indicator pane (when not in idle); others exist only in the status indicator pane; soft indicators: these are present only in the idle state.
9.4
Summary
In this chapter we have provided a description of panes. Panes are subcomponents of windows and they may themselves contain subpanes. There are three panes dividing the screen of a smartphone: status pane, main pane, and control pane. The status pane shows the application caption and icon, if these are dened in addition to battery and signal strength. The main pane is available for the application, although it is possible to allocate the whole screen for the application. The control pane shows the labels of the softkeys.
10
Lists and List Types
Lists are a common way to represent data in the Series 60 Platform. Lists can be separated roughly into vertical and two-dimensional grids, but there are many different layout types for lists. Many applications in Series 60 use vertical lists, but in some situations two-dimensional lists are very convenient. At the end of this chapter, there are examples on how to use lists. This chapter concentrates mainly on vertical lists.
LIST ARCHITECTURE
211
CListItemDrawer
MEikListBox Observer
CListBoxView
CEikListBox
MListBoxModel
MTextListBoxModel
CTextListBoxModel
MDesCArray
CEikListBox
CAknGrid
CEikTextListBox
CEikFormattedCellListBox
CEikColumnListBox
CEikSnakingListBox
CAknColumnListBox
CEikSnakingTextListBox
CAknSingleStyleListBox
CAknSingleNumberStyleListBox
Figure 10.2 Various types of lists in Series 60. Note: gray indicates a concrete class in Avkon
Figure 10.2 shows the architecture of various types of lists in the Series 60 Platform. There are four main categories: CAknGrid is the base class for two-dimensional lists, and CEikTextListBox is the base class for all vertical lists. Vertical lists are further divided in three different list types, based on their layout. Classes presented in gray boxes are concrete classes in Avkon (Nokia, 2001f).
212
Figure 10.3
Menu list
10.2.2
Selection List
Selection lists are a common way of displaying and accessing data in applications, shown in the main pane. In Figure 10.4, the selection opens a more detailed view.
LIST TYPES
213
same short message is sent to several people. The selection differs from markable lists. In multiselection lists, the selection is done only with the selection key, and acceptance is given with the Ok softkey.
214
Figure 10.6
Multiselection list
LIST TYPES
215
combinations: AB, BC, or ABC, but you cannot mix different layouts within a list. A dynamic column still exists after C, where additional icon indicators can be added. Additional icons can be added to every list item dynamically and therefore it is not the same kind of column as the other three (Nokia, 2001g).
Standard list item columns are as follows: column A: small graphic (icon) (Nokia, 2001g), item number (Nokia, 2001g); column B: heading (title or attribute of the item) (Nokia, 2001g); column AB: heading (title or attribute of the item) (Nokia, 2001g), large graphic (e.g. icon or image thumbnail) (Nokia, 2001g); column C/BC/ABC: main text of the item (Nokia, 2001g).
(a)
(b)
Figure 10.9 List styles: (a) graphic-style list and (b) number-style list
216
Table 10.1
List item types
Single-line item Single-line item with number Single-line item with heading Single-line item with graphic Single-line item with graphic and heading Single-line item with number and heading Single-line item with large graphic
CAknSingleHeadingStyleListBox
"Heading\tTextLabel\t0\t1"
CAknSingleGraphicStyleListBox
"0\tTextLabel\t1\t2"
CAknSingleGraphicHeadingStyleListBox "0\tHeading\tTextLabel\t1\t2"
CAknSingleNumberHeadingStyleListBox
"1\tHeading\tTextLabel\t2\t3"
CAknSingleLargeStyleListBox
"1\tTextLabel\t0"
Double item
CAknDoubleStyleListBox
"\tFirstLabel\tSecondLabel\t0"
Two-line item
CAknDoubleStyle2ListBox
"\tFirstLongLabel\t\t0"
LIST TYPES
217
CAknDoubleNumberStyleListBox
CAknDoubleTimeStyleListBox
"Time\tPM\tFirstLabel\tSecondLabel" Time has to consist of numbers and could be separated with. or:
CAknDoubleLargeStyleListBox
"1\tFirstLabel\tSecondLabel\t0" Recommended image sizes: 30 40, 36 44, 40 30, 40 48, 44 36. "0\tFirstLabel\tSecondLabel\t0" Where 0 is index for icon array
CAknDoubleGraphicStyleListBox
CAknFormDoubleGraphicStyleListBox "1\tFirstLabel\tSecondLabel\t0"
Double item
CAknFormDoubleStyleListBox
"\tFirstLabel\tSecondLabel\t0"
Setting item
CAknSettingStyleListBox
"\tFirstLabel\t\tValueText"
(continued overleaf )
218
Table 10.1
List item types
(continued )
Example picture Class name List item string format
Setting item
CAknSettingStyleListBox
"\tFirstLabel\t0\t"
Setting item
CAknSettingStyleListBox
"\tFirstLabel\t\tValueText\t*"
Setting item
CAknSettingStyleListBox
"\tFirstLabel\t\t\t\tSecondLabel"
CAknSettingNumberStyleListBox
Same as above four entries except that there is a number before the rst item: "1\tFirstLabel\t\tValueText" "FirstLabel\t0" "0\tLabel"
Single-line item Single-line item with graphic Single-line item with graphic
CAknSinglePopupMenuStyleListBox CAknSingleGraphicPopupMenuStyleListBox
CAknSingleGraphicBtPopupMenuStyleListBox "0\tLabel"
LIST TYPES
219
Single-line item with heading Single-line item with graphic and heading Double item
CAknSingleHeadingPopupMenuStyleListBox
"Heading\tLabel"
CAknSingleGraphicHeadingPopupMenuStyleListBox "0\tHeading\tLabel"
CAknDoublePopupMenuStyleListBox
"FirstLabel\tSecondLabel"
CAknDoubleLargeGraphicPopupMenuStyleListBox
"0\tFirstLabel\tSecondLabel"
CAknFormGraphicStyleListBox
220
10.3.1
We should make a member variable for the list, and CEikTextListBox is a base class for all vertical lists, so we can use that:
CEikTextListBox* iListBox;
Then we create an instance of this list, and construct it with a ag that denes what kind of list it will be (see Table 10.2):
iListBox = new (ELeave) CAknSingleStyleListBox; iListbox->SetContainerWindowL(*this); iListBox->ConstructL(this, EAknListBoxSelectionList); Table 10.2 Construct ags for vertical lists (from avkon.hrh) Flag EAknListBoxSelectionList EAknListBoxMenuList EAknListBoxMarkableList EAknListBoxMultiselectionList EAknListBoxLoopScrolling Type Selection list Menu list Markable list Multiselection list List can be looped from rst to last, and from last to rst. This cannot be used alone, but it can be appended with or operator (e.g. EAknListBoxSelectionList | EAknListBoxLoopScrolling)
For offering data for the list, we can make an instance of, for example, CDesCArrayFlat, and format items correctly before offering those to the list. It is also possible to use the default array of lists, but,
USE OF LISTS
221
as previously mentioned, it is not recommended. When we set a new array to the list model, the default array will be destroyed. The ownership type of the array can be changed with SetOwnershipType(), if it is preferable that the creator owns the array:
CDesCArray* array = new (ELeave) CDesCArrayFlat(5); CleanupStack::PushL(array); array->AppendL(_L("\tItem 1")); array->AppendL(_L("\tItem 2")); CleanupStack::Pop(); // array iListBox->Model()->SetItemTextArray(array);
Adding Items
If we want to add items dynamically, we have to ask for the item text array from the list model. The function ItemTextArray() is returning MDesCArray, so we have to know what kind of array it really is and change the type to that, to append more items to the array. After appending the item, the list has to be informed of item addition, so that it knows to redraw itself. Of course, it is possible to keep the pointer to array as a member variable to use it directly, but here the array is asked in the list box model:
CDesCArray* array = static_cast<CDesCArray*>(iListBox-> Model()-> ItemTextArray()); array->AppendL(_L("\tNew item")); iListBox->HandleItemAdditionL();
Removing Items
In some cases we need to remove items from the list. Again, we have to get the array from the list model. In the example below we remove a currently focused item. After deletion we have to set the current item index again, because of the highlight. The highlight means that the currently focused item is emphasized with some color (e.g. see Pat in Figure 10.5). In case the deleted item was the last, we have to set the current item to some other place; here, the last item will be set:
TInt currentItem( iListBox->CurrentItemIndex() ); if ( currentItem >= 0 ) { CDesCArray* array = static_cast<CDesCArray*>(iListBox-> Model()->ItemTextArray()); array->Delete(currentItem); if ( currentItem >= array->Count() ) // last item { currentItem = array->Count(); }
222
Scrollbars are needed if there are more items than one display can accommodate; they indicate the position of the currently focused item in a list. Creation of scrollbars can be done immediately after list creation, because the list shows scrollbars automatically if the number of items exceeds the display:
iListBox->CreateScrollBarFrameL(ETrue); iListBox->ScrollBarFrame()->SetScrollBarVisibilityL( CEikScrollBarFrame::EOff, CEikScrollBarFrame::EAuto);
Note: remember to offer your list in ComponentControl() and in CountComponentControls() and pass key events on the list in OfferKeyEventL() function. To be able to see the list, we still have to give the area where it is going to be drawn. The usual place for this is SizeChanged() function, where it could be done in the following way:
if ( iListBox ) { iListBox->SetRect( Rect() ); }
// do not change // what kind of list will be created, // see Table 10.2 WORD height = 5; // in items WORD width = 10; // in chars LLINK array_id = 0; // link to array definition }
USE OF LISTS array_id = r_list_box_array; flags = EAknListBoxMarkableList; } RESOURCE ARRAY r_list_box_array { items = { LBUF { txt = "1\tFirstLabel 1\tSecondLabel 1"; }, LBUF { txt = "2\tFirstLabel 2\tSecondLabel 2"; } }; }
223
224
LISTS AND LIST TYPES buttons = R_AVKON_SOFTKEYS_OK_BACK; items = { DLG_LINE { type = EAknCtDoubleNumberListBox; // see Table 10.3 id = ESelectionListControl; control = LISTBOX { flags=EAknListBoxSelectionList| EAknListBoxLoopScrolling; array_id = r_list_box_array; }; } } }
Table 10.3 List enumerations for dialogs (from avkon.hrh) Type EAknCtSingleListBox EAknCtSingleNumberListBox EAknCtSingleHeadingListBox EAknCtSingleGraphicListBox EAknCtSingleGraphicHeadingListBox EAknCtSingleNumberHeadingListBox EAknCtSingleLargeListBox EAknCtDoubleListBox EAknCtDoubleNumberListBox EAknCtDoubleTimeListBox EAknCtDoubleLargeListBox EAknCtDoubleGraphicListBox Class CAknSingleStyleListBox CAknSingleNumberStyleListBox CAknSingleHeadingStyleListBox CAknSingleGraphicStyleListBox CAknSingleGraphicHeadingStyleListBox CAknSingleNumberHeadingStyleListBox CAknSingleLargeStyleListBox CAknDoubleStyleListBox CAknDoubleNumberStyleListBox CAknDoubleTimeStyleListBox CAknDoubleLargeStyleListBox CAknDoubleGraphicStyleListBox
The rst parameter is used to return the item which was selected and the second parameter is a pointer to a list item array. In this example, the item array is created from the resource le, so we can ignore this parameter. Parameter aMenuBarResourceId is a resource identier (ID) for the menu bar, and the last parameter is used if one wishes to catch the option menu commands. The option menu is actually a menu bar, which contains menu panes (e.g. see the picture on the option menu
USE OF LISTS
225
in Figure 10.3). For these special dialogs, the menu bar has to consist of at least one menu pane and should be either:
R_AVKON_MENUPANE_SELECTION_LIST
or
R_AVKON_MENUPANE_SELECTION_LIST_WITH_FIND_POPUP
It is possible to add your own menu panes into the menu bar. In this example, we use only R AVKON MENUPANE SELECTION LIST, which is empty, and that is why we are dening buttons to R AVKON SOFTKEYS OK BACK. The resource denition for the menu bar is:
RESOURCE MENU_BAR r_menubar { titles = { MENU_TITLE { menu_pane = R_AVKON_MENUPANE_SELECTION_LIST; } }; }
The use of CAknMarkableListDialog is very similar to this, except that one can dene an array for the selection items (see the correct use in aknselectionlist.h).
226
Note that the rst icon from the icon array is used as the marking icon (see Figure 10.5, where selections are indicated with an icon on the right-hand side of the list item):
iListBox->ConstructL(this, EAknListBoxMarkableList);
How to set the icon array for the lists depends on the base class. If the base class is CEikFormattedCellListBox, icons are set with
iListBox->ItemDrawer()->FormattedCellData()-> SetIconArray(icons);
Notice that the function SetIconArray() changes ownership, and therefore we do not have to push the array on the cleanup stack. But if the ownership change is done later, remember to push the icon array to the cleanup stack before appending any items on it and pop it after appending. It is possible to append items to the list that is using icons. Actually, it does not matter whether you set an item text array before the icon array; just do not activate the container before setting the icon array. Note: example icons are used from avkon.mbm, so avkon.mbg should be included.
USE OF LISTS Table 10.4 Standard popup note layouts (from aknpopuplayout.h) AknPopupLayouts EMenuWindow EmenuGraphicWindow EMenuGraphicHeadingWindow EmenuDoubleWindow EMenuDoubleLargeGraphicWindow EPopupSNotePopupWindow Class used with the type
227
(e.g. CAknSinglePopupMenuStyleListBox). They are listed in Table 10.4. A popup menu example is shown in Figure 10.10. To be able to use CAknPopupList class we have to include
#include <aknPopup.h> CEikFormattedCellListBox* listBox = new (ELeave) CAknSinglePopupMenuStyleListBox; CleanupStack::PushL(listBox);
Before we can continue list creation we have to create a popup list. When creating a popup list we have to offer a list, soft keys, and a layout type in the NewL() function. Layout types can be found in Table 10.4 and in Table 10.7:
CAknPopupList* popupList = CAknPopupList::NewL( listBox, R_AVKON_SOFTKEYS_OK_BACK, AknPopupLayouts::EPopupSNotePopupWindow); CleanupStack::PushL(popupList); popupList->SetTitleL(_L("List"));
After the popup list, we can continue list creation. In ConstructL(), we offer a popupList as a parent for the list. Explanations for the ags can be found in Table 10.1:
228
listBox->ConstructL(popupList, EAknListBoxSelectionList|EAknListBoxLoopScrolling);
Then we continue with normal list construction, like setting scroll indicators and items for list model. After this, popup list is ready to be launched:
CleanupStack::Pop(); // popupList if (popupList->ExecuteLD()) { TInt index(listBox->CurrentItemIndex()); // do something with the current item index } else { // popup list canceled } CleanupStack::PopAndDestroy(); // listbox
10.3.6
Grids
Grids are not as developed in the Series 60 Platform as the vertical lists, so the application developer has to do more work than with vertical lists. Series 60 provides a common base class for all grids, which is then customized for applications. There are a few almost complete grids, and these are CAknPinbStyleGrid, CAknQdialStyleGrid, and CAknCaleMonthStyleGrid. Item string formatting for those can be found in Table 10.5. For construction, these grids are almost the same as vertical lists. You create, for example, an instance of CaknPinbStyleGrid, and the only thing that differs is enumeration EAknListBoxSelectionGrid and how to set the empty text:
iGrid = new (ELeave) CAknPinbStyleGrid; iGrid->ConstructL(this, EAknListBoxSelectionGrid); iGrid->SetContainerWindowL(*this); iGrid->SetEmptyGridTextL(_L("Empty grid\n Two lines of text"));
Table 10.5 Construct ags for grids (from avkon.hrh) Flag EAknListBoxSelectionGrid EAknListBoxMarkableGrid EAknListBoxMenuGrid Type Selection grid Markable grid Menu grid
USE OF LISTS
229
CellPinbPaneStyle
CAknPinbStyleGrid
CellQDialPaneStyle
CAknQdialStyleGrid
CellCalcMonthPaneStyle
CAknCaleMonthStyleGrid
"1\t2\tTxt"
230
However, you may need to make your own custom grid. This can be achieved in several ways, but here is one way to do it. You need to inherit a CAknGrid and override the SizeChanged() and MinimumSize() functions, which are virtual functions dened in CEikListBox. In the next example, we make a 4 4 grid of custom width, because there is no grid for that size (see Figure 10.11).
Table 10.7 Standard popup note layouts without resizing (from aknpopuplayout.h)
AknPopupLayouts EDynMenuWindow EDynMenuGraphicWindow EDynMenuGraphicHeadingWindow EdynMenuDoubleWindow EDynMenuDoubleLargeGraphicWindow Class used with the type CAknSinglePopupMenuStyleListBox CAknSingleGraphicPopupMenuStyleListBox CAknSingleGraphicHeadingPopupMenuStyleListBox CAknDoublePopupMenuStyleListBox CAknDoubleLargeGraphicPopupMenuStyleListBox
USE OF LISTS
231
This can also be done in the resource with SetLayoutFromResourceL(). The resource structures used with the grid are as follows:
STRUCT GRID { BYTE version = 0; // do not change WORD flags = 0; // type of grid WORD height = 5; // in items WORD width = 10; // in chars LLINK array_id = 0; // link to item array LTEXT emptytext = ""; // what is shown if grid // is empty LLINK style = 0; // GRID_STYLE } STRUCT GRID_STYLE { WORD layoutflags = 0; WORD primaryscroll=0; WORD WORD WORD WORD WORD WORD WORD }
// items layout, see Table 10.8 // primary scroll behavior, // see Table 10.9 secondaryscroll=0; // secondary scroll behavior, // see Table 10.9 itemsinprimaryorient = 0; // how many items // primary oriently itemsinsecondaryorient=0; // how many items // secondary oriently height = 0; // cell height width = 0; // cell width gapwidth = 0; // gap between cells gapheight = 0; // gap between cells
Table 10.8 Grid layout ags (from avkon.hrh) Flag EAknGridHorizontalOrientation EAknGridVerticalOrientation EAknGridRightToLeft EAknGridLeftToRight EAknGridBottomToTop EAknGridTopToBottom Description Items are appended horizontally and, if items do not t on the screen, the grid is expanded vertically Items are appended vertically and, if items do no t on the screen, the grid is expanded horizontally Items are appended from right to left Items are appended from left to right Items are appended from bottom to top Items are appended from top to bottom
232 Table 10.9 Grid scroll ags (from avkon.hrh) Primary scroll EAknGridFollowsItemsAndStops EAknGridFollowsItemsAndLoops
Description Focus follows grid and stops when edge of grid has been reached Focus follows grid and loops back to beginning when edge of grid has been reached
With layout ags, we dene our primary orientation. The orientation can be horizontal or vertical, and primary and secondary scrolling follows that style:
RESOURCE GRID_STYLE r_grid_style { layoutflags = EAknGridHorizontalOrientation | EAknGridLeftToRight | EAknGridTopToBottom; primaryscroll = EAknGridFollowsItemsAndStops; secondaryscroll = EAknGridStops; itemsinprimaryorient = 4; itemsinsecondaryorient = 4; height = 44; // this doesnt affect, because // it is overridden when // creating sub cells width = 44; // same thing, but these // have to be defined gapwidth = 0; gapheight = 0; }
The SizeChanged() function determines the layout of the grid; here, We set what the cells are going to look like and what they will contain. The cell in Figure 10.12 consists of two subcells: icon and text.
To dene the subcells in the cell, we can use a utility class called AknListBoxLayouts (see aknlists.h); some calculation is needed before setting the start and end positions of subcells:
void CMyOwnGrid::SizeChanged() { CAknGrid::SizeChanged();
USE OF LISTS
233
The SizeChanged() function cannot leave, so we have to trap the creation of subcells. We have to get a pointer to the item drawer to set up the subcells:
TRAPD(error, { CAknGrid& aListBox = *this; CFormattedCellListBoxItemDrawer* itemDrawer = aListBox.ItemDrawer();
First, we set the default foreground, background colors, and grid position. Position values should be constant, so they can easily be changed and understood. For instance, the const TInt KMainCellWidth=44 and TInt KMainCellHeight=44, or they can be calculated if you wish to make a very exible and customizable grid:
AknListBoxLayouts::SetupStandardGrid(aListBox); AknListBoxLayouts::SetupGridPos(aListBox, 0, 0, -1, -1, KMainCellWidth, KMainCellHeight);
AknListBoxLayouts::SetupFormAntiFlickerTextCell( aListBox, itemDrawer, 1, LatinBold12(), KFontColor, KLeftMargin, KNotUsed, KBaseLine, KWidth, CGraphicsContext::ELeft, TPoint(0, 0), TPoint(EMainCellWidth,EMainCellHeigth));
Of course, there should be exact calculations for the base line and for all the position values. Transparent cells can also be created, so that they do not overlap with some other lower-level cell:
itemDrawer->FormattedCellData()-> SetTransparentSubCellL(1, ETrue); } ); // TRAPD ends } // SizeChanged ends
234
At the same time that subcells are created, we dene our customized way of formatting items in a grid. Our rst subcell is an icon, and the second is a text, hence the format is:
array->AppendL(_L("1\\tTxt"));
where number 1 is an index for the icon array. Then we can construct our example grid from the resource le, and items can also be set from the resource le, or they could be set later. However, the icon array has to be set manually and not from the resource le.
Figure 10.13 List with one item separated into two rows
Engine
CMyEngine provides a very simple contact database to which it is possible to add contacts. It uses its own data class, called CMyContact, where it is possible to store a name and a number (see Figure 10.14). For this type of data, it is convenient to create an array of pointers to CMyContact.
CArrayPtr<CMyContact>* iArray;
USE OF LISTS
235
CBase
Engine CMyContact
iArray
0..*
CMyEngine
View
Unfortunately, it is not possible to place an engine array straight in the list, because the base class is not MDesCArray. That is why it is practical to use the adapter design pattern (Gamma et al., 2000) to adapt the engine data to MDesCArray. This is done in the CMyListBoxModel of the view. This is the reason why this model has to be inherited from MDesCArray, as seen in Figure 10.15. CMyListBoxModel also formats data, so that the list is able to show the data correctly.
CBase
MDesCArray
View CMyListBoxModel
Application
In Figure 10.16 the application architecture is shown as a whole. In the application package, CListBoxView owns a container, which has CEikFormattedCellListBox. This list is actually instantiated to CAknDoubleStyleListBox, which shows one item separated into two rows, as seen in Figure 10.13.
236
engine CMyEngine
CAknView
CCoeControl
MDesCArray
CEikFormattedCellListBox
CTextListBoxModel
A code example will further clarify this application. In the next subsection we will go through the key elements of an example.
Code Analysis
CListBoxViewContainer creates a list in its ConstructL() function. The actual instance of the class will be CAknDoubleStyleListBox. CMyEngine and CMyListBoxModel are also created in CListBoxViewContainer. A reference to the engine is given to the model, which enables access to contacts. The model is given to CTextListBoxModel, which uses CMyListBoxModel as an MDesCArray to provide data to be shown in the list. It is possible to give ownership to the list model or to keep it in the application. Here, the ownership is changed with SetItemTextArray() to CTextListBoxModel:
CMyListBoxModel* model = CMyListBoxModel::NewL(*iEngine); iListBox->Model()->SetItemTextArray(model); // changes ownership
Before we can show data stored in the engine, we have to implement the model to offer the data in the correct format for the list. CMyListBoxModel is derived from MDesCArray, so we have to implement two functions that are dened as pure virtual in MDesCArray (see bamdesca.h). First, we implement MdcaCount(), which is very simple; it just returns the count of items in the engine:
return iEngine.Count();
USE OF LISTS
237
In order to implement MdcaPoint, we have to do a little bit more work. When the list draws visible list items in the screen, these are asked for from MDesCArray through MdcaPoint. MdcaPoint is always used when the list draws something where the list does not copy or use pointer/reference when showing items. Visible items are only in the screen buffer, not as a text, but as pixels. For example, if you press down the arrow to move in the list, the viewable items in the list are all redrawn and therefore asked from the model. The implementation depends on whether the array is static or dynamic. If data in the array do not change and the size is quite small, the best way is probably to do a static array in the resource le. If the array is dynamic and the size can be quite large, it is advisable format each item separately. Since the lists do not copy or use reference for list items, it allows the possibility of using a single buffer in the model to format items for the list. Implementing the buffer could be done with, for instance, an automatic class variable mutable TBuf<256> iBuffer. This type of buffer works very well in the Series 60 Platform, because Series 60 is not designed for wide screens. That is why 256 characters is sufciently long to show the needed list items with formatting parameters. Mutable is used, because MdcaPoint is constant and cannot therefore change the member data, but mutable allows mutating (i.e. modifying) even constant data. In this example, a dynamic buffer is used with an initial size of 50. This size is chosen to ensure that the model is always able to offer something for the list. If reallocation fails, we can still use the buffer that was initially created. Of course, with every application, it should be considered whether the user should be informed about potential data loss. This means that some data could be missing at the end of the list item, which could be critical in some stockmarket applications, for example. Below, we show the implementation for MdcaPoint and CMyListBoxModel, which uses HBufC* iBuffer for formatting data. In the example, the data are rst fetched from the engine. If the current buffer size is not sufciently long, a new allocation is needed. MdcaPoint cannot leave, and that is why it reallocates with ReAlloc() and checks the return value whether the reallocation was successful. If the reallocation was successful, we have to make iBuffer to point to the new data area, because HBufC is always allocated as a single cell and the previous address may be to an invalid area in the memory where the iBuffer used to reside. In case of failure, we keep using the old buffer:
const CMyContact* contact = iEngine.GetContact(aIndex); TPtrC name( contact->Name() );
238
TPtrC number( contact->Number() ); // there is going to be two tabulatures, because of formatting TInt length( name.Length() + number.Length() + (KTab().Length() * 2) ); if ( iBuffer->Des().MaxLength() < length ) { HBufC* tmp = iBuffer->ReAlloc(length); // Do not destroy the old buffer if allocation has failed! if (tmp) { iBuffer = tmp; } }
We then simply append the data to the buffer with label separators, but before we actually add the original data to the buffer we have to remove possible tabs (\t) from the data, otherwise, the list would show items incorrectly:
TPtr buffer( iBuffer->Des() ); buffer.Zero(); buffer.Append(KTab); AppendAndRemoveTabs(buffer, name); buffer.Append(KTab); AppendAndRemoveTabs(buffer, number); return *iBuffer;
10.4 Summary
Now we have concluded the lists chapter and know that there are many different layouts and many ways to construct lists. The use is challenging, but the basic idea is the same with all lists. Some container needs to own an instance of a list and for that, item icon arrays must be set. The abstract class MDesCArray makes it possible to create exible systems that can hide complicated data structures and makes using them easy.
11
Other User Interface Components
In this chapter, a large number of Series 60 Platform user interface (UI) controls are described. These vary from user notication controls to setting pages. There are not that many controls, but every one has some variations that are used for different situations. To assist in the selection of the proper UI controls for particular situations, refer to the Series 60 UI style guide (Nokia, 2001g). This book is not intended to override that document, but is an aid to constructing the control chosen from the style guide.
11.1
Dialogs
In the Series 60 Platform, the dialog architecture has some new features. The dialogs are capable of having menus. This is implemented in the CAknDialog class, which derives from CEikDialog. Applications should use dialogs derived from this class if they need dialogs with a menu. If they do not, they can still derive from CEikDialog (e.g., if one needs only the softkey buttons for selection). An example dialog is shown in Figure 11.1. The CAknDialog uses the same dialog resource, DIALOG, as in the previous platform versions, except that now a MENU_BAR resource is needed for the menu. The menu bar and dialog resources are dened separately. The ConstructL() function of CAknDialog takes the menu bar resource identier (ID) and loads it from the resource le. The derived class can implement the DynInitMenuPaneL() function, which is called just before the menu is launched. In this function, the menu may be formatted according to the current application or focus state:
void CMyAknDialog::DynInitMenuPaneL (TInt aResourceId, CEikMenuPane* aMenuPane)
240
Figure 11.1
In the Series 60 menu, items are dimmed instead of deleted. A dimmed item is not shown in the menu; there are no dimmed menu items at all. This is done to make scrolling of the menus easier to use. The menus are faster to use and can contain more items when there are no dimmed items. Make sure the correct menu pane is in question when dimming items; this is done by comparing aResourceId against the intended menu pane. Every menu pane present in the menu bar receives its own DynInitMenuPaneL() call. In our experience, the best practice is to include all possible menu items in the resource and use dimming as the only strategy to alter the menu context. Also, the derived class must implement the ProcessCommandL() function. Here, selected menu items are handled. The unhandled commands are forwarded to the application user interface:
iEikonEnv->EikAppUi()->HandleCommandL(aCommandId);
The OkToExitL() function is called when a softkey is pushed. The dialog state can be veried and then return to ETrue if the dialog can be closed.
FORMS
241
11.2
Forms
Forms are special types of dialogs, as shown in Figure 11.2. They can be in either view or edit state. The item layout and functionality can differ between the two states. In the view state, the elds are not editable; it looks and acts like a listbox. The listbox focus can be moved, and items can be selected. In the edit state, the form elds can be edited; it may contain text elds, popup elds, and sliders. The state can be switched by using a menu item. In some cases, the view state is not used at all and the form is always in the editable state. The menu can also be disabled if it seems inappropriate to the situation.
The editable form may be in one- or two-line format. In the one-line style, the optional icon is the left-most, followed by the label, editor, and second icon. The forms also use DIALOG resource structures. In the following example, the last item of the resource structure, form, is used as a link to the FORM structure:
RESOURCE FORM r_my_dynamic_form { flags = EEikFormShowBitmaps | EEikFormUseDoubleSpacedFormat; }
The FORM structure contains two elds: the ags, and items for the form. The ag eld sets the modes of the form. The left-most icon is enabled with the EEikFormShowBitmaps ag and the two-lined form state with the EEikFormUseDoubleSpacedFormat ag. In a static form, the form items can be dened in this resource as DLG_LINEs. If the content of the form is dynamic the items section can be left blank. The form items are constructed dynamically in the form PreLayoutDynInitL() function, using the CreateLineByTypeL() function.
242
The form can contain various controls. Below, we will discuss the editor controls individually. The editors can expand to multiple lines dynamically, depending on the input length. Up and down arrows are used to navigate between elds in the form. In some situations, where we want to group certain controls together, a separator can be used. The CAknForm class has several virtual functions that can be used to implement specic features into the Series 60 form control. The SaveFormDataL() function can be overridden to implement specic save logic to a form. For example, a note could be shown if saving is not possible. The DoNotSaveFormDataL() can be used to reset the editor values to their previous values. The QuerySaveChangesL() function default implementation presents a save conrmation query. This can also be overridden to customize the query. The virtual EditCurrentLabelL() function displays the old label as a caption, and the editor is used to retrieve the new label. The DeleteCurrentItemL() presents a query about deleting the currently focused form eld and then deletes the form line depending on this result. AddItemL() is used to add a eld to the form.
11.3 Editors
There are several new editor modes in the Series 60 user interface. These range from telephone number editors to secret editors for passwords and such. With the possibility of having a predictive text-entry system, extra care has to be taken when setting the editor ags. These can depend on the input type for the retrieved data. The mode of the predictive text-entry system has to be controlled and the special character set veried for each editor. These ags can be set through a resource structure that has been added to support the above. The edwin, global text and rich text editor resource structures that the Series 60 editors use are extended to include an AKN_EDITOR_EXTENSIONS structure. This contains ags for the default case, allowed case modes, numeric key map, allowed input modes, default input mode, special character table, and a ags eld. The denitions are in the UIKON.hrh le.
EDITORS Table 11.1 Allowed editor cases Allowed case mode EAknEditorUpperCase EAknEditorLowerCase EAknEditorTextCase EAknEditorAllCaseModes Description
243
Upper-case input only Lower-case input only Automatic change from upper case to lower case; rst letter is in upper case. User is able to switch between upper-case and lower-case input
When the editor is constructed dynamically the SetAknEditorCase() and SetAknEditorPermittedCaseModes() functions can be used to manipulate the case mode, as shown in Figure 11.3.
SetAknEditorNumericKeymap() function can be used when the editor is constructed dynamically. In Figure 11.4 a number editor is presented in a two-line form.
Figure 11.4
244
Figure 11.5
The SetAknEditorSpecialCharacterTable() function can be used when the editor is constructed dynamically, but you still have to have a resource for the table. Avkon resources contain the special character tables shown in Table 11.3. The content of these can vary depending on the active character case and locale.
11.3.5 Flags
This eld allows the setting of various attributes to the editors. The value of these ags can also be set by using the SetAknEditorFlags() function. The ags are listed in Table 11.4.
NOTIFICATIONS Table 11.3 Special character tables Special character table resource id r_avkon_special_character_table_dialog r_avkon_url_special_character_table_dialog Description
245
r_avkon_email_addr_special_character_table_dialog
r_avkon_currency_name_special_character_table_dialog
The default special character table Contains the special characters that are available in an URL address eld Contains all possible special characters available in an e-mail address eld The special characters that are used in the currency name editor; they must be 7-bit ASCII characters.
Table 11.4 Editor ags Flag EAknEditorFlagDefault EAknEditorFlagFixedCase EAknEditorFlagNoT9 EAknEditorFlagNoEditIndicators EAknEditorFlagNoLRNavigation EAknEditorFlagSupressShiftMenu EAknEditorFlagEnableScrollBars EAknEditorFlagMTAutoOverwrite EAknEditorFlagUseSCTNumericCharmap EAknEditorFlagLatinInputModesOnly Description Resets the ag bits (it is dened as 0x000) Disables the case change possibility. Disables the predictive text input (T9) system Disables the editor indicator Disables left-key and right-key navigation in the editor Disables the use of the special character table from the shift key (ABC) Enables the scrollbar indicator for the editor Enables automatic overwriting of text. Enables the numeric character map Enables only Latin character input modes
11.4
Notications
Notes are a feedback component that informs the user about the current situation. They contain text and a graphical icon that classies the notes to the following categories. They do not have softkeys except for the wait note, which can contain a cancellation in some situations.
246
There are two ways to show a conrmation note. First, using the CAknNoteDialog class with the fully dened DIALOG resource:
CAknNoteDialog* dlg = new (ELeave) CAknNoteDialog( CAknNoteDialog::EConfirmationTone, CAknNoteDialog::EShortTimeout); dlg->ExecuteLD(R_MY_CONFIRMATION_NOTE);
You must give the correct tone and time-out parameters for each of the note types. The resource denition for the note is shown in the example below:
RESOURCE DIALOG r_my_confirmation_note { flags = EAknConfirmationNoteFlags; buttons = R_AVKON_SOFTKEYS_EMPTY; items = { DLG_LINE { type = EAknCtNote; id = EConfirmationNote; control = AVERELL_NOTE { layout = EGeneralLayout; singular_label = "note text"; imagefile = "z:\\system\\data\\avkon.mbm"; imageid = EMbmAvkonQgn_note_ok; imagemask = EMbmAvkonQgn_note_ok_mask; animation = R_QGN_NOTE_OK_ANIM; }; } }; }
There is also a possibility for having a plural label for the note text. The label text can be set dynamically using the SetTextL() function. The plural mode can be set by using the SetTextPluralityL() function with ETrue as the parameter. The SetTextNumberL() function sets the number of the plural texts to the one indicated by the parameter. This function works for resource and dynamically set texts. The number is inserted where the \%d string is in the descriptor.
NOTIFICATIONS
247
For example: "Delete \%d items" would become "Delete 30 items". If you have multiple formatting needs in your string, you can use the string loader component and then set the text. Notice how all the static note type information has to be dened over and over again for different notes. This can become a very heavy updating procedure. Combined with localization, it can cause considerable binary size bloat if your application has many notes. The second method of note construction is far more resource-friendly. Use the above method only if you need to divert from the standard note types or need some special features. In other cases, it is strongly recommended that note wrappers, described below, be used. The second method for making a note is use of the note wrapper component. The class CAknConfirmationNote has all the tones and icons already set on a central resource structure:
CAknConfirmationNote* note = new(ELeave) CAknConfirmationNote; note->ExecuteLD(_L("prompt"));
The ExecuteLD takes the prompt text as a parameter, so no resource denition is needed, only the prompt text. This can be loaded from a resource buffer and then formatted, if needed. Using this will save you some space in your resource le, and you do not have to worry about the correct tone and icon parameters.
Figure 11.7
Information note
The rst method needs the correct parameters for the note. Refer to Section 11.4.1, on conrmation notes, on how to create the CAknNoteDialog and the resource structure for the note. For the tone, the
248
parameter is EConfirmationTone and ELongTimeout time for the length. The resource structure must have the ID EAknInformationNoteFlags and the correct icon for the information note. The note wrapper class for this type of note is CAknInformationNote:
CAknInformationNote* note = new(ELeave) CAknInformationNote; note->ExecuteLD(_L("prompt"));
The use is similar to that for the conrmation note. This is one advantage when using the wrappers: you have only to change the created object in order to change the note type:
The rst method needs the correct parameters for the note. Refer to Section 11.4.1, on conrmation notes, on how to create the CAknNoteDialog and the resource structure for the note dialog. For the tone, the parameter is EErrorTone and ELongTimeout time for the length. The resource structure must have the correct ID EAknWarningNoteFlags and the icon for the information note. The wrapper class for the warning note is CAknWarningNote:
CAknWarningNote* note = new(ELeave) CAknWarningNote; note->ExecuteLD(_L("prompt"));
NOTIFICATIONS
249
Figure 11.9
Error note
Information notes are always used when there is no irreversible error. Error notes should be used very wisely. An example error note is shown in Figure 11.9. The rst method needs the correct parameters for the note. Refer to Section 11.4.1, on conrmation notes, on how to create the CAknNoteDialog and the resource structure for the note. For the tone, the parameter is EErrorTone and ELongTimeout time for the length. The resource structure must have the correct ID EAknErrorNoteFlags and the icon for the information note. The wrapper class is CAknErrorNote for the error note:
CAknErrorNote* note = new(ELeave) CAknErrorNote; note->ExecuteLD(_L("prompt"));
250
Using the above resource as a parameter for the PrepareLC() function, and then calling RunLD() executes the static note:
CAknStaticNoteDialog* dlg = new(ELeave) CAknStaticNoteDialog; dlg->PrepareLC(R_MY_NOTIFICATION); dlg->SetNumberOfBorders(4); if (dlg->RunLD()) { <<positive response>> }
The RunLD returns a positive value if the response is accepted and a negative value if declined. The SetNumberOfBorders() function sets the number of borders visible to the user. It can be used to indicate that there are additional unhandled soft notications in the queue.
If a long-running operation is run synchronously with an application, the application freezes for the duration of the operation. This can be very confusing to the user; the application would appear to have stalled. In order to solve this problem the user is presented with a wait or progress note while the long process is run. When the process is completed, the wait note is dismissed. In order to get a wait note on the screen, you need to make an active object that has a wait note dialog and that then runs the long, synchronous, operation in small portions. The long operation is divided into smaller units of execution. It is not possible to issue the wait note
NOTIFICATIONS
251
and then start the long synchronous operation and, when that returns, dismiss the wait note without an active object. The wait note is never drawn on the screen! Again, there are two methods for doing this. An example of a wait note is shown in Figure 11.11.
The basic method is to make the active object wait note oneself. This has to be done when the long-running operation contains another service request one would have to wait for (e.g. when one would have to wait for a notication of a data structure being ready for use). The CAknWaitDialog and CAknProgressDialog classes implement the wait note and progress note components. The CAknWaitDialog derives from CAknProgressDialog, which has most of the application programming interface (API) for the functionality. In order for clients to receive notication when the user has dismissed the note, the DialogDismissedL function of the MProgressDialogCallback interface must be implemented; the parameter is the button ID of the user-pressed key. To set the client to receive this call, the SetCallback() function must be used:
iWaitDialog = new(ELeave) CAknWaitDialog( REINTERPRET_CAST (CEikDialog**, &iWaitDialog)); iWaitDialog->SetCallback(this); iWaitDialog->ExecuteLD(R_MY_WAIT_NOTE);
252
OTHER USER INTERFACE COMPONENTS { layout = EWaitLayout; singular_label = "Copying"; imagefile = "z:\\system\\data\\avkon.mbm"; imageid = EMbmAvkonQgn_note_copy; imagemask = EMbmAvkonQgn_note_copy_mask; animation = R_QGN_GRAF_WAIT_BAR_ANIM; }; } }; }
The CAknProgressDialog constructor takes the nal value, increment, interval, and a self-pointer as parameters. The CEikProgressInfo class controls the progress bar; a handle to this can be retrieved from the progress dialog GetProgressInfoL() function. Through this class, the increment of the progress bar can be controlled by using the IncrementAndDraw() function. When the process is nished, the progress dialog ProcessFinishedL() function must be called. The progress dialog also uses the DIALOG resource structure:
RESOURCE DIALOG r_my_progress_note { flags = EAknProgressNoteFlags; buttons = R_AVKON_SOFTKEYS_CANCEL; items = { DLG_LINE { type = EAknCtNote; id = EProgressNote; control = AVERELL_NOTE { layout = EProgressLayout; singular_label = "deleting items"; imagefile = "z:\\system\\data\\avkon.mbm"; imageid = EMbmAvkonQgn_note_progress; imagemask = EMbmAvkonQgn_note_progress_mask; }; } }; }
The second way to do this is by using a wait note wrapper. The above situation is so similar and common that a wait note runner can eliminate most of the hardest active object handling work. The CAknWaitNoteWrapper class is an active object that already owns a wait note control. What the client needs to implement is the MAknBackgroundProcess interface that then makes the callbacks to the wait note wrapper client. The CAknWaitNoteWrapper class
NOTIFICATIONS
253
ExecuteL function takes the wait note resource ID, the interface implementer object, visibility delay, tone setting, and, optionally, the prompt text parameters. When the wrapper is executed, an active object service request is made. When the active scheduler services the wait note request, the MAknBackgroundProcess implementer object IsProcessDone() function is called. This function determines whether the client process is done. If it returns EFalse, a single step of the process is executed by calling the StepL() function, and another service request is made. If it returns to Etrue, the ProcessFinished() function is called; this signals the client that the process is done. The sequence diagram of the wait note wrapper is shown in Figure 11.12.
Interface MAknBackgroundProcess
NextCycle()
If the StepL() function leaves, the client CycleError() function is called with the error code as a parameter. If the client is able to handle this error and the process can logically continue it should return to KErrNone. All other errors are escalated to the active scheduler. If the user dismisses the wait note, the client DialogDismissedL() function is called with the softkey button ID as a parameter:
254
The R_MY_WAIT_NOTE resource structure is similar to the wait note structure used above.
11.4.7
Soft Notications
Soft notications are reminders to the user that a certain event has taken place (e.g. that an incoming text message has arrived). The user can respond to these with the softkeys. The left softkey is used to proceed with the appropriate action, and the right to dismiss the notication event. Soft notications are shown only in the idle state. This means that when an event occurs and the user is using an application and chooses to ignore the event, such as an incoming call, the notication is shown when he or she returns the idle state of the phone. There are two different appearance styles for soft notications: ungrouped and grouped. Ungrouped notications contain a single notication, and they use the same control as notes. Grouped notications can contain many different notication items. The control used in this situation is a list query, where the user can choose an item from the list. In the case where many ungrouped notications are active, they are stacked on top of each other. After the top-most is handled, the one behind appears. Notications have a priority that determines the order of the stack. The application that issued the soft notication can discard it without the user being involved. Notications should remain active as long as the event is pending. The notication can be discarded when a user reacts to the event, even though he or she has not seen the soft notication. At the moment there is no way or any need for third-party applications to issue soft notications. Though the CAknSoftNotifier class is the interface for the notications, you might want to check if all the functions are in fact private and thus cannot be used for your client code. All the classes that can use soft notications are friends to this class. If a public interface for it appears, applications can issue soft notications.
11.5 Queries
Queries are used in situations where the user needs to select a way to proceed or requires user input, or validation of the selected action. There are several different types of queries for these situations.
QUERIES
255
The Series 60 Platform contains local and global queries. Local queries are local to a certain application. For instance, switching to another application hides a local query, but is again shown when the user switches back to the original application. Global queries are systemwide queries, and are shown on top of everything; so, switching to a different application still shows a global query. The following types of queries are dened and described below in detail: conrmation query data query list query multiselection list query
Conrmation queries are used to conrm an action from the user or to answer a yesno type of question. For example, before deleting an item, the query is shown to conrm that the user does not accidentally delete something important. The layout of the query is the same as the note window, with an optional graphic icon. As seen from the following example, the CAknQueryDialog class is used with the dialog resource for the conrmation query:
CAknQueryDialog* dlg = CAknQueryDialog::NewL(); dlg->SetPromptL(*prompt); if(dlg->ExecuteLD(R_MY_GENERAL_CONFIRMATION_QUERY)) { }
256
The SetPromptL method is used to set the prompt text for the query. The R_MY_GENERAL_CONFIRMATION_QUERY resource is standard DIALOG resource structure:
RESOURCE DIALOG r_my_general_confirmation_query { flags = EGeneralQueryFlags; buttons = R_AVKON_SOFTKEYS_YES_NO; items = { DLG_LINE { type = EAknCtQuery; id = EGeneralQuery; control = AVKON_CONFIRMATION_QUERY { layout = EConfirmationQueryLayout; }; } }; }
When dened, the ags for the dialog are usually the EGeneralQueryFlags and the softkeys that are used for the query. The EGeneralQueryFlags sets these ags, as shown in Table 11.5.
Table 11.5 Flag EEikDialogFlagWait EEikDialogFlagNoDrag EEikDialogFlagNoTitleBar EEikDialogFlagCbaButtons Dialog ags Description Makes this dialog modal; the ExecuteLD returns when the dialog is dismissed The dialog window cannot be moved The title bar of the dialog is not used The CBA buttons are enabled; in this case they are the softkeys
The conrmation dialog contains one item of type EAknCtQuery with the EGeneralQuery ID. The control contains the conrmation query resource structure. This denes the layout of the conrmation query and the static label for the control.
Data Query
A data query contains a prompt text and an input editor (see Figure 11.14). Data queries are used in some situations where an application requires user input. The editors can accept alphanumeric
QUERIES
257
or numeric information, depending of the type of the data query. There are several possible data query types for different situations. The CAknTextQueryDialog is used for querying alphanumeric text, secret text, a phone number, or the PIN (personal identication number) code from the user:
CAknTextQueryDialog* dlg = CAknTextQueryDialog::NewL (editText, *prompt); dlg->SetMaxLength(aMaxLength); dlg->ExecuteLD(R_MY_TEXT_QUERY);
The editText is the descriptor that is used for the editor; prompt is the descriptor that contains the prompt text for the query. The prompt text can also be described in the resource structure of the query. SetMaxLength() sets the maximum length of the text editor. The parameter for the ExecuteLD() is the resource structure for the query. The used structure is a standard DIALOG resource structure:
RESOURCE DIALOG r_my_text_query { flags = EAknGeneralQueryFlags; buttons = R_AVKON_SOFTKEYS_OK_CANCEL; items = { DLG_LINE { type = EAknCtQuery; id = EGeneralQuery; control = AVKON_DATA_QUERY { layout = EDataLayout; control = EDWIN { }; }; } }; }
258
The structure is similar to conrmation query resource structure. The only difference is the contained control structure, which is an AVKON_DATA_QUERY resource. This structure again contains the layout of the query, the static label, and the control used in the query. The layout and control mappings for the different editors are listed in Table 11.6.
Table 11.6 Layout and control mappings for editors Type Alphanumeric text Secret editor Phone number PIN code Layout EDataLayout ECodeLayout EPhoneLayout EPinLayout Control EDWIN SECRETED EDWIN SECRETED
The resource-dened prompt text is static, so you cannot format its run-time. In most cases, this is just what is needed. To do this, you need to insert a second DLG_LINE before the editor dialog line. This time, the type of the line is an EAknCtPopupHeadingPane and the ID EAknMessageQueryHeaderId. The control structure is an AVKON_HEADING that contains a label eld where you insert your prompt text. Also, the optional bitmap icons are dened here. The le that contains the bitmap is put to bmpfile and the ID of the bitmap and its mask is set to bmpid and bmpmask. CAknNumberQueryDialog, shown in Figure 11.15, is used when a number input is needed. The API is very similar to that of a data query. The NewL constructor takes a reference to the integer typed parameter that is altered to contain the user input. The SetMinimumAndMaximum() function allows one to set the minimum and maximum values for the editor. The resource structure is similar to that of a data query, except that the contained EDWIN control is replaced by a NUMBER_EDITOR structure, containing the compulsory initial minimum and maximum values. When using the SetMinimumAndMaximum() function, one must note that the parameter values must be between the initial minimum and maximum values.
QUERIES
259
CAknTimeQueryDialog, shown in Figure 11.16, is used for requesting a time or a date. The NewL() constructor takes a reference to a TTime object that is altered by the user. The SetMinimumAndMaximum() function acts in the same way as in the CAknNumberQueryDialog. The resource structure is similar to that of a data query except for the control, which has a DATE_EDITOR structure. It initializes the minimum and maximum dates for the editor. When used for querying the time, the control structure is replaced by a TIME_EDITOR that contains the minimum and maximum time values.
CAknDurationQueryDialog, shown in Figure 11.17, is used for getting the time duration. The NewL() constructor parameter is a reference to a TTimeIntervalSeconds object. The resource structure is similar to that of a data query, except that the layout is an EDurationLayout and the control is DURATION_EDITOR. This structure describes the minimum and maximum duration for the editor.
CAknFloatingPointQueryDialog, shown in Figure 11.18, is used for oating point input. The NewL takes a TReal reference that is modied by the user input. The resource layout is an EFloatingPointLayout and the controls resource structure is a FLPTED. The maximum and minimum values and the length of the number can be initialized here. CAknMultiLineDataQueryDialog, shown in Figure 11.19, is used for queries that have multiple editors. At the moment it is two at the maximum. There are varying sets of NewL() constructors for possible input situations. These all take reference parameters for the editors.
260
The resource structure now contains two dialog lines instead of one. A date and time multiline data query resource structure would be:
RESOURCE DIALOG r_date_and_time_multiline_query { flags = EGeneralQueryFlags; buttons = R_AVKON_SOFTKEYS_OK_CANCEL; items = { DLG_LINE { type = EAknCtMultilineQuery; id = EMultilineFirstLine; control = AVERELL_DATA_QUERY { layout = EMultiDataFirstDateEd; label = "Enter Date:"; control = DATE_EDITOR { minDate = DATE {year=1986;}; maxDate = DATE {year=2060;}; flags=0; }; }; }, DLG_LINE { type = EAknCtMultilineQuery; id = EMultilineSecondLine;
QUERIES
261
control = AVERELL_DATA_QUERY { layout = EMultiDataSecondTimeEd; label = "Enter Time"; control = TIME_EDITOR { minTime = TIME {second=0;minute=0;hour=0;}; maxTime = TIME {second=59;minute=59;hour=23;}; flags=0; }; }; } }; }
The dialog line type is EAknCtMultilineQuery for both of the lines. The ID determines the multiline line number; for the rst line it is EMultilineFirstLine and for the second it is EMultilineSecondLine. Then the controls are as for a the general data query.
List Query
The list query, an example of which is shown in Figure 11.20, is a list of possible selections, of which the user must select one. It can contain a heading at the top of the popup window, if chosen. Below, there is a list of possible choices; the handling of the softkeys and the selection key is similar to the conrmation query. Also, a grid component can be used instead of a list:
TInt index = 0; CAknListQueryDialog* dlg = new(ELeave) CAknListQueryDialog(&index); if(dlg->ExecuteLD(R_MY_LIST_QUERY)) { \\ ok pressed }
The CAknListQueryDialog class takes the integer pointer parameter that contains the index of the selection after the list has been
262
executed. When the dialog is dismissed, ExecuteLD() returns the softkey ID that was pressed. The list query uses an AVKON_LIST_QUERY resource structure:
RESOURCE AVKON_LIST_QUERY r_my_list_query { flags = EGeneralQueryFlags; softkeys = R_AVKON_SOFTKEYS_OK_CANCEL; items = { AVKON_LIST_QUERY_DLG_LINE { control = AVKON_LIST_QUERY_CONTROL { listtype = EAknCtSinglePopupMenuListBox; listbox = AVKON_LIST_QUERY_LIST { array_id = r_listbox_item_list_array; }; heading = "prompt"; }; } }; }
In the source code example above we have an AVKON_LIST_ QUERY_DLG_LINE, containing an AVKON_LIST_QUERY_CONTROL that denes the listbox type. The AVKON_LIST_QUERY_LIST contains a resource link to the array of items in the list:
RESOURCE ARRAY r_listbox_item_list_array { items = { LBUF {txt = "1\tFirst"; }, LBUF {txt = "1\tSecond"; }, LBUF {txt = "1\tThird"; } }; }
A dynamic list query can be constructed with a CAknPopupList class that takes an existing listbox control and makes it a popup frame with an optional heading. The NewL constructor takes any CEikListBox derived listbox, the command button array (CBA) resource ID, and a popup layout type as a parameter. Even though this might appear to be a dialog and has an ExecuteLD() function as well, it is not a dialog. The ExecuteLD() returns after the popup has been dismissed; the return value is true if it is accepted. The user is responsible for deleting
QUERIES
263
the popup list object. The SetTitleL() function can be used to set the title of the popup window. Only the following styles of listboxes work with the popup list: CAknSinglePopupMenuStyleListBox CAknSingleGraphicPopupMenuStyleListBox CAknSingleGraphicHeadingPopupMenuStyleListBox CAknSingleHeadingPopupMenuStyleListBox CAknDoublePopupMenuStyleListBox CAknDoubleLargeGraphicPopupMenuStyleListBox
The CAknListQueryDialog constructor takes a CListBoxView::CSelectionIndexArray pointer that will contain the selected items indices after the query has executed. This CSelectionIndexArray can be any CArrayFix deriving class. In the example below it is a CArrayFixFlat; what you must watch out for here is the cleanup stack the listbox does not take ownership of it, so it must be on the cleanup stack:
CArrayFixFlat<TInt>* array = new(ELeave)CArrayFixFlat<TInt>(3); CleanupStack::PushL(array); CAknListQueryDialog* dlg = new(ELeave) CAknListQueryDialog(array); if(dlg->ExecuteLD(R_MY_MULTI_SELECTION_LIST_QUERY)) { // ok pressed } CleanupStack::PopAndDestroy(array);
264
The resource structure is somewhat similar to that of a list query, but it has its own structures and types:
RESOURCE AVKON_MULTISELECTION_LIST_QUERY r_my_msl_query { flags = EGeneralQueryFlags; softkeys = R_AVKON_SOFTKEYS_OK_CANCEL; items = { AVKON_MULTISELECTION_LIST_QUERY_DLG_LINE { control = AVKON_LIST_QUERY_CONTROL { listtype = EAknCtSingleGraphicPopupMenuListBox; listbox = AVKON_MULTISELECTION_LIST_QUERY_LIST { array_id = r_listbox_item_list_array_icons; }; heading = "prompt"; }; } }; }
The multiselection list needs a listbox array that has tabs (the correct tab listing is given in Chapter 10):
RESOURCE ARRAY r_listbox_item_list_array_icons { items = { LBUF {txt = "1\tYes"; }, LBUF {txt = "1\tNo"; }, LBUF {txt = "1\tMaybe"; } }; }
SETTING VIEWS
265
if (iAOObserver) { iAOObserver->Cancel(); delete iAOObserver; } iAOObserver = new(ELeave) CMyGlobalConfirmationObserver(iEikonEnv); iAOObserver->Start(); //SetActive iGlobalConfirmationQuery->ShowConfirmationQueryL(iAOObserver->iStatus, iPrompt, R_AVKON_SOFTKEYS_OK_CANCEL, R_QUERY_NOTE_ANIMATION);
One must be extra careful that the prompt text object exists when the query is shown. On completion, the request status will contain the pressed softkey ID. The CMyGlobalConfirmationObserver object RunL function is executed when the query is dismissed.
11.6
Setting Views
All application-specic settings should be collected to a special settings page. The setting pages are specialized screens for the manipulation of certain controls. These are presented in a list to the user. If the list is long it can be split into different views by using tabs, or into a hierarchical settings tree. The setting structure is presented topdown, starting from the setting listbox. The settings are collected and presented in specialized setting item listboxes. Some of these setting items are modied through editors in specic setting pages.
266
in various places, such as in a control in a view architecture view, or as part of a multipage dialog. The content of the setting list is likely to be very stable, and the best place to load the list is in the resources. The resource structure used is an AVKON_SETTING_ITEM_LIST. This structure contains the title and an array of AVKON_SETTING_ITEM structures for the contained items. An example of a setting list resource is as follows:
RESOURCE AVKON_SETTING_ITEM_LIST r_my_setting_item_list { title = "My settings"; initial_number = 2; items = { AVKON_SETTING_ITEM { identifier = EMyDateSettingId; setting_page_resource = r_my_date_setting_page; name = "Date"; }, AVKON_SETTING_ITEM { identifier = EMyNumbersSettingId; name = "Number"; type = EEikCtEdwin; setting_editor_resource = r_my_numbers_edwin; compulsory_ind_string = "*"; } }; }
The identifier is a unique ID for the setting item. The setting_page_resource is a link to an AVKON_SETTING_PAGE
SETTING VIEWS
267
resource that determines the appearance of the setting page. The setting_editor_resource overrides the previous resource by dening a link to an editor; when this is used, the type of the editor must also be specied. The compulsory_ind_string is used to show a special index character on the setting item list; in this case, it is a * character. You must derive your own setting list class from CAknSettingItemList. To load the setting list resource you should call the ConstructFromResourceL() function of the CAknSettingItemList class. The base class has a CreateSettingItemL() function that needs to be overridden. The purpose of this function is to construct a setting item that corresponds to a specic ID. When the setting item is constructed, the item constructor usually requires the editable value to be passed. This is then shown to the user in the list. The setting list owns a CAknSettingItemArray. In some situations, you will want to create the setting listbox dynamically. This is done by constructing the wanted setting listbox (e.g. a CAknSettingStyleListBox). This listbox is then lled and formatted with the setting texts, such as a standard listbox. The view is made an observer of the listbox. The listbox generates events, for example, when a selection is made, and then calls the client HandleListBoxEventL(). From this function, using the current listbox index, we launch the correct setting page.
268
Table 11.7 Setting items and the pages they create Setting item class CAknTextSettingItem CAknIntegerSettingItem CAknPasswordSettingItem Corresponding setting page class CAknTextSettingPage CAknIntegerSettingPage CAknAlphaPasswordSettingPage or CAknNumericPasswordSettingPage, depending on the password mode CAknVolumeSettingPage CAknSliderSettingPage can be overridden with CreateAndExecuteSettingPageL and CreateSettingPageL CAknTimeSettingPage or CAknDateSettingPage, depending on the mode. CAknIpFieldSettingPage CAknPopupSettingPage CAknPopupSettingPage
CAknVolumeSettingItem CAknSliderSettingItem
CAknTimeOrDateSettingItem
page. The method for constructing and executing the setting page is described below. The CAknSettingPage is a base class for all the different setting page types. These deriving setting pages then own one of the controls mentioned below. Possible controls and the setting page classes that contain them are listed in Table 11.8. In this example case, the owner is a CAknVolumeSettingPage. For example the volume setting is as in Figure 11.23.
Table 11.8 Setting page classes and controls Setting page class CAknSliderSettingPage CAknVolumeSettingPage CAknTextSettingPage CAknIntegerSettingPage CAknTimeSettingPage CAknDateSettingPage CAknDurationSettingPage CAknAlphaPasswordSettingPage CAknNumericPasswordSettingPage CAknCheckBoxSettingPage CAknPopupSettingPage CAknRadioButtonSettingPage Control CAknSlider CAknVolumeControl CEikEdwin CAknIntegerEdwin CEikTimeEditor CEikDateEditor CEikDurationEditor CEikSecretEditor CAknNumericSecretEditor CAknSetStyleListBox
The slider, volume, radio button, and text setting pages manipulate a single value, but the checkbox allows for multiple selected items. The resource structure used for the setting pages is an AVKON_SETTING_PAGE. This is used for all the setting page types
SETTING VIEWS
269
by changing the values of the structure. For instance, a volume setting page resource could be:
RESOURCE AVKON_SETTING_PAGE r_my_volume_setting_page { label = "Volume"; softkey_resource = R_AVKON_SOFTKEYS_OK_BACK; type = EAknCtVolumeControl; editor_resource_id = r_my_volume_control; }
The editor_resource_id is a link to the setting page control of the type dened by the type line above it. The control would then be:
RESOURCE VOLUME r_my_volume_control { flags = EMyVolumeControl; value = 10; }
A setting page may have its own menu. This is dened by the menubar link, which works similarly to dialog menus. In this case, you will also want to change the softkey_resource. Menus are generally used with settings lists. Also, some optional features such as a setting item number, setting text description, and a navigation pane hint text are supported. The mapping of the different control types and the resource structures they use is given in Table 11.9. The CAknSettingPage class has set and get functions for overriding the resource-dened functions. This can be used for context-sensitive texts and for setting the index. The various setting page deriving classes also have constructors that take the needed
270
Table 11.9 Control types and their resource structures Setting page type Slider Volume Text Integer Time Date Duration Radio button list, Check Box Numeric secret editor IP address editor Popup list Control type EAknCtSlider EAknCtVolumeControl EEikCtEdwin EAknCtIntegerEdwin EEikCtTimeEditor EEikCtDateEditor EEikCtDurationEditor EAknSetListBox EAknCtNumericSecretEditor EAknCtIpFieldEditor EAknCtPopupSettingList Resource structure SLIDER VOLUME EDWIN AVKON_INTEGER_EDWIN TIME_EDITOR DATE_EDITOR DURATION_EDITOR LISTBOX NUMSECRETED IP_FIELD_EDITOR POPUP_SETTING_LIST
data as parameters. These can be used instead of using resourcedened structures. In most cases, the control needs to be dened in a resource anyway. The specic setting page constructor usually takes the setting value as a reference parameter. This reference is updated according to the ExecuteLD() parameter. The check box setting page uses a particular CSelectionItemList class to handle the text and their selection states. It is basically an array that contains CSelectableItem objects. The items contain the item text and its selection status, as shown in Figure 11.24.
Setting pages are like modal dialogs, the ExecuteLD() sticks, but events may still occur and run to other parts of the application code. The parameter determines whether the parameter passed by the reference is changed whenever the editor is changed or only when the page is dismissed. The setting page is constructed and executed in the setting list according to the user selection:
SUMMARY
CAknVolumeSettingPage* dlg = new (ELeave)CAknVolumeSettingPage( R_MY_VOLUME_SETTING_PAGE, volume); if (dlg->ExecuteLD(CAknSettingPage::EUpdateWhenChanged)) { //Accepted, set system volume to new value }
271
11.7
Summary
The reader should now be familiar, visually and codewise, with the available controls that can be used in applications. All the frustrating work of nding which enumerations and ags belong to which type of control should be made a little easier with use of the relevant tables in this chapter. It is hoped this chapter will help developers implement their applications with fewer bugs and in less time.
12
View Architecture
To aid maintainability and exibility, Series 60 Platform applications are commonly split into two distinct parts, the engine and the user interface. In this chapter, the focus will be on how the user interfaces from separate applications can cooperate together to provide the end user with a seamless way of navigating the functionality in the platform.
VIEW DEPLOYMENT void CMyAppUi::ConstructL() { // Initialize base class BaseConstructL(); // Create an application view CAknView* view; view = CMyFirstView::NewL(); // Register the view with the framework CleanupStack::PushL( view ); AddViewL( view ); CleanupStack::Pop(); // Set this as the default view ActivateLocalViewL( view->Id() ); // Create and register another view view = CMyOtherView::NewL(); CleanupStack::PushL( view ); AddViewL( view ); CleanupStack::Pop(); }
273
A view is identied by the system with a unique identier (UID) value that is unique within the application. Each of the view classes should implement an identier method that returns the view UID. As the class CAknView is derived from the class CBase, it is instantiated with the conventional Symbian construction process. However, since only one view is active within an application at a time, it is best to use all UI-specic construction and destruction code in the DoActivateL() and DoDeactivate() methods. It is important to note that one should always check within the DoActivateL() method whether a view is already active, to avoid resource leaks. This is advisable, since by having only a single view active, the memory consumption and system resource usage is signicantly decreased. Finally, a HandleCommandL() method is needed in the view to handle user-originated events. An example implementation of these methods is shown below; as views do not own any pieces of the screen themselves, each view must own at least one window-owning control:
// Construct a view. This method is called only once during the // lifetime of the object. void CMyFirstView:ConstructL() { // Load view-specific data from resource file BaseConstructL( R_MYFIRSTVIEW ); } // DoActivateL is called each time when a view is activated // For example, this occurs when the user starts a new application // or the active view in the foreground is changed by the system itself void CMyFirstView::DoActivateL( const TVwsViewId& /* aPrevViewId */, TUid /* aCustomMessageId */, const TDesC8& /* aCustomMessage */ )
274
VIEW ARCHITECTURE
{ // Create view container control that will then create // all child controls if( !iContainer ) { iContainer = new ( ELeave ) CMyFirstViewContainer( *this ); iContainer->ConstructL( AppUi()->ClientRect() ); iContainer->SetMopParent( this ); // Add the container to the control stack // So that it and its children can receive key events AppUi()->AddToViewStackL( *this, iContainer ); // Complete the initialization iContainer->ActivateL(); } }
// DoDeactivate is called whenever a view is deactivated void CMyFirstView::DoDeactivate() { // The controls are not needed anymore. Remove them to save // memory. if( iContainer ) { AppUi->RemoveFromViewStack( *this, iContainer ); delete iContainer; iContainer = NULL; } }
It is customary for views to have a command button array (CBA) and a menu. These can be specied within the application resource le using a resource structure of type AVKON VIEW. The name of the resource has to be passed as a parameter in the method BaseConstructL() during view initialization. An example of the resource is shown below:
// This resource is located in the application resource file. // RESOURCE AVKON_VIEW r_myfirstview { // Define the softkeys. Certain commonly used softkeys are // pre-defined in avkon.hrh cba = R_AVKON_SOFTKEYS_OPTIONS_EXIT; // Define the contents of the options menu. This should be // present in the same resource file as this view resource. menubar = r_myfirst_view_menubar; }
The relationships of the various view-related classes are shown in Figure 12.1.
12.1.2
VIEW DEPLOYMENT
275
CEikAppUi
CBase
MCoeView
MEikMenuObserver
CAknAppUi
CMyAppUi
CMyView1
CMyView2
CMyView3
Figure 12.1
applications in the system. Any application that supports views can easily be launched if the view UID and application UID are known. For the view switches within the context of a single application, a method ActivateLocalViewL() of the class CAknViewAppUi is used. For interapplication transitions, the same class provides the method ActivateViewL(). An example of the use of each of these is shown below:
// // // // Switch to a new view within the same application The information needed is the view UID. The UIDs for all views should preferably be located in a single header file.
AppUi->ActivateLocalViewL( KMyOtherViewUID ); // // // // // // Switch to a view within another application. The necessary information is the application UID and view UID. This is a method of the class CAknView, unlike the above, which comes from CAknViewAppUi. The helper class TVwsViewId is used to store the UID values.
276
VIEW ARCHITECTURE
For more complex applications, it is necessary to parameterize the views. An example of this may be a day view of a calendar application. The content of the view is naturally parameterized by a specic date. For applications launching this view, a mechanism is necessary to pass this extra information to the calendar day view class. This is made possible by the interview messaging mechanism. A view that needs to be parameterized can receive a special, custom-dened message ID and message string parameters for use in the DoActivateL() method at the time of activation. Other applications can then pass the message and the ID to the view activation calls that were discussed above. An example of this more complex interaction is as follows:
// An example implementation of the parameterized view CMyCalendarDayView::DoActivateL( const TVwsViewId& /* aPrevViewId */, TUid aCustomMessageId, const TDesC8& aCustomMessage ) { // Create view container control that will then create // all child controls if( !iContainer ) { if( aCustomMessageId == KStartDayView ) { TUint8 day = aCustomMessage[0]; iContainer = new ( ELeave ) CDayViewContainer( *this ); iContainer->SetMopParent( this ); iContainer->ConstructL( day, AppUi()->ClientRect() ); // Add the container to the control stack // So that it and its children can receive key events AppUi()->AddToViewStackL( *this, iContainer ); // Complete the initialization iContainer->ActivateL(); } } } // Within application code, parameterized views can be launched // as follows TVwsViewId targetView( KTargetAppUid, KTargetViewUid ); // Create the message buffer TBufC8<1> dayBuffer; dayBuffer[0] = 15; // Launch the view ActivateViewL( targetView, KStartDayView, dayBuffer );
If you want your application views to be accessible to other applications, it is recommended to document the usage. At least view, message UID, and syntax should be dened in the documentation. In practice, this is accomplished by including the information in a separate header le.
277
12.2
12.2.1
278
VIEW ARCHITECTURE
Owing to the way in which the current view server is implemented, crashing applications or badly programmed applications with long UI delays can pose a problem for the overall usability of the platform. The view server can terminate a currently active application if it has hung or remains otherwise unresponsive for a prolonged period of time. In this manner, other applications in the platform eventually become accessible. However, the developers are responsible for guaranteeing that no major loops or delays exist within applications.
12.3 Summary
The view architecture makes it possible to create solid applications that can interact easily with each other. By implementing a view-based application, the developer can make the software more maintainable, reduce the memory footprint, and take advantage of reusable views.
13
Audio
In this chapter we discuss how to use different sounds in own applications. The Series 60 Platform currently supports three different audio formats: basic monophonic sinewave tones, WAV format sound clips, and MIDI format polyphonic tunes. In this chapter, we also describe how to record and stream WAV format audio. When programming audio software for the Series 60 Platform, an important point to be noted is that every sound utility has a priority value. By that value, it is possible, for example, to let the phone ring when a phone call comes or short message arrives. Sound utilities, playing, recording, and so on are asynchronous operations. Handling these operations is done by a callback interface. The sound utility classes have their own M classes that describe the appropriate callback methods for the class to take care of asynchronous operations. An observer has to exist for every audio client. A single observer can observe more than one player or recorder. This chapter includes example implementation for methods that are essential for enabling the use of sounds in own applications. The class diagram of the audio components is given in Figure 13.1. CMyTonePlayer, CMyAudioPlayer, CmyRecorder, and CMyStreamer are the classes used in the example codes.
13.1
Playing
The Series 60 Platform includes three player classes for different purposes: one for playing sinewave tones, one for playing WAV sound clips and other supported formats, and one for streaming audio. The support for additional audio formats is done by media server plugins. Currently, in Series 60 there is a plug-in for polyphonic MIDI songs.
280
AUDIO
CMyTonePlayer
CMyAudioPlayer
CMyRecorder
CMyStreamer
PLAYING
281
13.1.1
Priorities
All playing requests have to have a priority. Through the priority value, Media Server chooses the client that has the highest priority to play and gives the playing shift for that. The priority value range is from 100 to 100. The default priority value is zero. The priority value also has a priority preference. By that value, the audio driver decides what to do to the playing process in the lower-priority player. This decision is made when another client makes a playing request with a higher priority. The priority values and preferences are described in Avkon.hrh. It is very important to set a priority value and preference to every playing request. If such values are not set, the player clients request will receive the previous requests priority and preference.
282
// virtual const virtual virtual virtual virtual virtual // virtual virtual };
AUDIO
void PrepareToPlayTone(TInt aFrequency, TTimeIntervalMicroSeconds& aDuration)=0; void PrepareToPlayDTMFString(const TDesC& aDTMF)=0; void PrepareToPlayDesSequence(const TDesC8& aSequence)=0; void PrepareToPlayFileSequence(const TDesC& aFilename)=0; void PrepareToPlayFixedSequence(TInt aSequenceNumber)=0; void CancelPrepare()=0; void Play()=0; void CancelPlay()=0;
class MMdaAudioToneObserver { public: virtual void MatoPrepareComplete(TInt aError)=0; virtual void MatoPlayComplete(TInt aError)=0; };
When adding a sinewave player to your own application, there has to be an observer class derived from the appropriate M class. The observer class also has to have implementations for methods described in the M class. Calling NewL() method creates an instance of the player class. This method takes a reference to an observer as a parameter. The observers methods are called when the preparation is completed or when the playing has ended. Both of those methods could be called with an error value. If everything has gone ne, the parameter has KErrNone as a value. If there is an error it should be handled by the player class developer. Below, we present an example implementation of initializing the player utility and starting playback. The CMyTonePlayer class is derived from MMdaAudioToneObserver, so it also implements the callback methods. In this case, the audio utility is prepared to play a le-based ringing tone. The format of the le sequence is described in the Smart messaging specication (Nokia, 2000). The playing volume and the priority of the utility can only be set when the player has been prepared successfully, otherwise a panic is raised. The implementation is as follows:
Void CMyTonePlayer::ConstructL() { iMyToneUtility = CMdaAudioToneUtility::NewL(*this); // KFile has complete path and filename of a ringing tone. iMyToneUtility->PrepareToPlayFileSequence(KFile); } void CMyTonePlayer::Play() { iMyToneUtility->Play(); }
PLAYING
283
void CMyTonePlayer::MatoPrepareComplete(TInt aError) { // If error occurred things below cannot be done. if (!aError) { iMyToneUtility->SetVolume(iMdaAudioToneUtility->MaxVolume()); iMyToneUtility->SetPriority(0, EMdaPriorityPreferenceTime); } else { // error handling. } } void CMyTonePlayer::MatoPlayComplete (TInt aError) { If (aError) { // error handling. } }
284
AUDIO
virtual void Stop()=0; virtual void SetVolume(TInt aVolume)=0; virtual void SetRepeats(TInt aRepeatNumberOfTimes, const TTimeIntervalMicroSeconds& aTrailingSilence)=0; virtual void SetVolumeRamp(const TTimeIntervalMicroSeconds aRampDuration)=0; // Query functions virtual const TTimeIntervalMicroSeconds& Duration()=0; virtual TInt MaxVolume()=0; };
class MMdaAudioPlayerCallback { public: virtual void MapcInitComplete(TInt aError, const TTimeIntervalMicroSeconds& aDuration)=0; virtual void MapcPlayComplete(TInt aError)=0; };
Differences between the audio clip player and the tone player are that the priority value and preferences are given to the audio clip player when it is created. These cannot be changed later, for instance, with the tone player. Control functions and query functions cannot be used before the player utility has been successfully initialized. If an error occurs during preparation and query or control methods are called, it causes the player to panic. The init callback function has the length of the initialized audio clip in microseconds as a parameter to check whether if the initialization has gone successfully:
void CMyAudioPlayer::ConstructL(const TDesC& aFileName) { // KFile has complete path and filename of WAV file iMdaAudioPlayerUtility = CMdaAudioPlayerUtility::NewFilePlayerL(KFile, *this); } void CMyAudioPlayer::MapcInitComplete(TInt aError, const TTimeIntervalMicroSeconds& aDuration) { // If error occurred things below cannot be done. if (!aError) { iPlayer->SetVolume(iPlayer->MaxVolume()); iPlayer->Play(); } else { // error handling. } } void CMyAudioPlayer::MapcPlayComplete(TInt aError) { If (aError)
PLAYING
{ // error handling. } }
285
The player class is derived from the MMdaAudioPlayerCallback class; the player class also implements callback methods. There is no need to dene the audio format before use. The recognition of the format and codec is done from the header of the audio clip. Playing of the example is started right after initialization.
13.1.4 Streaming
An audio stream can be used when continuous audio data play is required (e.g. for many wave clips after each other, or if the audio data come continuously from another device or application). Currently, the streaming supports WAV format audio that has been recorded with sample rate 8 kHz or 16 kHz and 16 bits per sample. The audio stream is a media server plug-in:
class CMdaAudioOutputStream : public CBase { public: IMPORT_C static CMdaAudioOutputStream* NewL(MMdaAudioOutputStreamCallback& aCallBack, CMdaServer* aServer = NULL); // virtual void SetAudioPropertiesL(TInt aSampleRate, TInt aChannels) = 0; virtual void Open(TMdaPackage* aSettings) = 0; virtual TInt MaxVolume() = 0; virtual TInt Volume() = 0; virtual void SetVolume(const TInt aNewVolume) = 0; virtual void SetPriority(TInt aPriority, TMdaPriorityPreference aPref) = 0; virtual void WriteL(const TDesC8& aData) = 0; virtual void Stop() = 0; virtual const TTimeIntervalMicroSeconds& Position() = 0; protected: CMdaAudioOutputStream(); }; class MMdaAudioOutputStreamCallback { public: virtual void MaoscOpenComplete(TInt aError) = 0; virtual void MaoscBufferCopied(TInt aError, const TDesC8& aBuffer) = 0; virtual void MaoscPlayComplete(TInt aError) = 0; };
The audio stream should be created by the NewL() method, which takes the appropriate M-class observer as a parameter. The initializing
286
AUDIO
is done by calling the streams open method, which must be called before use. If the opening of the stream has been done successfully, the MaosOpenComplete() callback method is called with KErrNone value. After successful callback, the properties of the audio, playing volume, and priority can be set and audio writing to the player plug-in buffer can be started. The callback method MaosBufferCopied() is called when the buffer has been copied to the server. Playback will be started when the rst buffer has been copied to the player plug-in, or when the player plug-ins own buffer is full. When the playing position reaches its end in the player plug-ins buffer, and there is no audio data waiting to be copied in the plug-in buffer, the callback method MaosPlayComplete() is called with error code KErrUnderFlow. If the playing is terminated by calling the Stop method, the callback method MaosBufferCopied() is called with KErrAbort error code for every buffer that has not yet copied the player plug-ins buffer. The callback method MaosPlayComplete() is also called with error code KErrCancel. The WriteL() method can be called for copying the audio data to plug-in at anytime and many times after successful initialization of the stream. There is no need to wait for callback of the buffer copy. A wave audio sound clip (load from a le) is used to describe the stream usage is the example below:
void CMyStreamer::ConstructL() { // reading wave to buffer TInt size(0); TInt headerBytes(44); iFs.Connect(); // KStreamFile has complete path and filename of WAV file iFile.Open(iFs, KStreamFile, EFileRead); iFile.Size(size); // member variable HBufC8* iBuffer iBuffer1 = HBufC8::NewL(size - headerBytes); // size of audio data = whole size - headers (44 bytes in PCM // wave) TPtr8 ptr1(iBuffer1->Des()); // read the data after headers iFile.Read(headerBytes, ptr1); iFile.Close(); // creating an Instance of stream. iMyAudioOutputStream = CMdaAudioOutputStream::NewL(*this); TMdaAudioDataSettings settings; settings.Query();
PLAYING
287
settings.iSampleRate = TMdaAudioDataSettings::ESampleRate8000Hz; settings.iChannels = TMdaAudioDataSettings::EChannelsMono; //Open the stream. iMyAudioOutputStream->Open(&settings); } void CMyStreamer::PlayL() { // same buffer is sent twice to player plug-in. iMyAudioOutputStream->WriteL(*iBuffer1); iMyAudioOutputStream->WriteL(*iBuffer1); } void CMyStreamer::MaoscOpenComplete(TInt aError) { if (aError == KErrNone) { TRAPD(err, iMyAudioOutputStream->SetAudioPropertiesL( TMdaAudioDataSettings::ESampleRate8000Hz, TMdaAudioDataSettings::EChannelsMono)); if (err) { // error handling } iMyAudioOutputStream->SetVolume( iMyAudioOutputStream->MaxVolume() ); } } void CMyStreamer::MaoscBufferCopied(TInt aError, const TDesC8& aBuffer) { if(aError != KErrUnderflow && aError !=KErrAbort) { // error handling } } void CMyStreamer::MaoscPlayComplete(TInt aError) { if (aError == KErrUnderflow ) { // playing has ended. } else if (aError !=KErrCancel) { // error handling. } }
The CMyStreamer class is an observer for the stream in this example. In the construction phase, the audio is read rst to an 8-bit buffer descriptor. The audio data, which is needed to send to the stream player plug-in, should not have any header information in the data. The PCM wave format audio has 44 bytes header information.
288
AUDIO
When the callback method MaosOpenComplete() has been called with KErrNone value, the audio properties and the playing volume are set. Every callback method should have appropriate error handling done by the streaming class developer to handle possible error situations correctly.
13.2 Recording
It is possible to record audio samples in different types of wave formats and codecs. Through the recorder utility it is also possible to play and edit audio samples. By using this class, it is also possible to play audio data from a certain position or play a described playing window. The recorder utility class is derived from the clip utility class that offers editing and different playing options for the recorder:
class CMdaAudioRecorderUtility : public CMdaAudioClipUtility { public: enum TDeviceMode { EDefault=0, ETelephonyOrLocal=EDefault, ETelephonyMixed=1, ETelephonyNonMixed=2, ELocal=3 }; public: // Static constructor IMPORT_C static CMdaAudioRecorderUtility* NewL( MMdaObjectStateChangeObserver& aObserver, CMdaServer* aServer=NULL, TInt aPriority=EMdaPriorityNormal, TMdaPriorityPreference aPref=EMdaPriorityPreferenceTimeAndQuality); // Open existing file to playback from / record to virtual void OpenFileL(const TDesC& aFilename)=0; // Open existing audio data in memory to playback from / record to virtual void OpenDesL(const TDesC8& aData)=0; // Open generic audio object virtual void OpenL(TMdaClipLocation* aLocation, TMdaClipFormat* aFormat, TMdaPackage* aArg1 = NULL, TMdaPackage* aArg2 = NULL)=0; // Set the audio device to use virtual void SetAudioDeviceMode(TDeviceMode aMode)=0; // Control the volume/gain on the audio device virtual TInt MaxVolume()=0;
RECORDING
virtual TInt MaxGain()=0; virtual void SetVolume(TInt aVolume)=0; virtual void SetGain(TInt aGain)=0; virtual void SetVolumeRamp(const TTimeIntervalMicroSeconds& aRampDuration)=0; }; class MMdaObjectStateChangeObserver { public: virtual void MoscoStateChangeEvent(CBase* aObject, TInt aPreviousState, TInt aCurrentState, TInt aErrorCode)=0; };
289
The enumeration TDeviceMode describes the behavior of the device when recording or playing. Different play modes are decided by a phone call: whether there is a phone call in progress or not. The local setting always plays the audio from the device speaker and records the audio from the device microphone. The telephony nonmixed setting plays the audio only to a phone call; audio is not played from the device speaker. Recording is done only for audio that comes from a phone call; the device microphone is not used. For the telephony mixed setting, the recording and playing is done only when a phone call is in progress. A default setting records the audio from a phone call and microphone and plays the audio to a phone call and speaker, if a phone call is in progress. If there is no phone call in progress, the recording is done only through the microphone and the playing is done through the device speaker. First, the recorder utility has to be created by the NewL() method and after that, an appropriate open method should be called. The recorder utility has only one callback method, which has four parameters: the rst represents the object that has changed the state; the previous and the current states describe what has happened, and the error code is for error handling. The different states are described in the audio clip utility class. The states are ENotReady, EOpen, EPlaying, and ERecording. To set the device mode, gain, and volume, the utility has to be in the state EOpen, EPlaying, or ERecording. In the following example, the CMyRecorder class has been derived from the observer interface M class. In the constructing phase, the utility class is created and the recording target is chosen as a le. The sample rate and number of channels are also set. The number of channels must be one if the device does not support stereo playback; otherwise it panics. All properties are given as a parameter to the opening method, also containing the audio format and codec. In the callback method, after successful initialization of the recorder, the device mode and gain for the recording are set:
290
AUDIO
void CMyRecorder::ConstructL() { iMdaAudioRecorderUtility = CMdaAudioRecorderUtility::NewL(*this); // recording settings: TMdaAudioDataSettings audioSettings; audioSettings.iSampleRate = 8000; audioSettings.iChannels = 1; // recording file: TMdaFileClipLocation fileClipLocation; // KRecorderFile has complete path and filename of WAV file fileClipLocation.iName = KRecorderFile; TMdaWavClipFormat wavFormat; TMdaImaAdpcmWavCodec imaAdpcmWavCodec; iMdaAudioRecorderUtility->OpenL(&iFileClipLocation, &wavFormat, &imaAdpcmWavCodec, &audioSettings)); } void CMyRecorder::RecordL() { // Set the position to the beginning of audio data. iMdaAudioRecorderUtility->SetPosition(TTimeIntervalMicroSeconds(0)); // delete data from playing position to the end of data. iMdaAudioRecorderUtility->CropL(); // start recording. iMdaAudioRecorderUtility->RecordL(); } void CMyRecorder::Play() { // Maximum volume for playback. iMyRecorder->SetVolume( iMdaAudioRecorderUtility->MaxVolume() ); // Set the position to the beginning of audio data. iMyRecorder->SetPosition( TTimeIntervalMicroSeconds(0) ); // Start playing. iMyRecorder->Play(); } void CMyRecorder::MoscoStateChangeEvent(CBase* /*aObject*/, TInt aPreviousState, TInt aCurrentState, TInt aErrorCode) { if (aErrorCode) { // error handling. } If ( aCurrentState == EOpen && aPreviousState == ENotReady) { // set the device mode. iMdaAudioRecorderUtility->SetAudioDeviceMode( CMdaAudioRecorderUtility::ELocal);
SUMMARY
291
13.3
Summary
In this chapter we have described how to use sound in applications. Three audio formats are currently supported by the Series 60 Platform: sinewave tones, WAV, and MIDI. In audio programming, application priorities are important. Otherwise, it is possible that ones audio application will block the phone ringing or some other alarm tone. The preparation of playing or recording involves the use of asynchronous operations, the handling of which is done with a callback interface provided by M classes. This chapter has described how to use these classes in audio applications.
14
Customizing the Series 60 Platform
This chapter discusses issues related to customizing the Series 60 Platform for a new device as well as porting from other user interface (UI) styles to Series 60. Not everything is needed in every case, and there are different levels of customization. The Series 60 Platform is a functional software package, from the operating system to a large set of applications. Still, it is always customized before the devices are shipped. How much customization is required depends on many things; one of the most important issues to consider is self-evident: time to market. It is quite possible that a device manufacturer can start developing multiple products at the same time. For one device, the platform is customized only as little as required to make it available as soon as possible, whereas with the other products the amount of customization and thus the difference from the original platform is greater. Figure 14.1 shows the parts that the device manufacturer must provide. One division breaks the various tasks into three tasks: UI customization, to achieve a certain branding of the device, through modication of the application suite, changing the UI appearance; base porting, to have the Symbian OS base work with the underlying hardware; telephony system integration, to enable communication of the cellular phone system and Symbian OS. Here, the tasks are covered with some explanation of what can and cannot be done. However, this is still an introduction to the topic and the reader should not expect full details on every aspect, as the details fall beyond the scope of this book. Another thing that should be noted
293
Licensee App 1 Series 60 Platform App 2 App 3 Series 60 GUI App engines LAF
App n
App m
Symbian core GUI Application engines EText, CONE, ... Comms EUser Kernel
Symbian
Figure 14.1 Series 60 Platform divided between the platform itself and the parts provided by Symbian and the device manufacturer. Note: App., application; GUI, graphical user interface; LAF, look and feel; CONE, control environment; comms, communications; DLL, dynamic link library
is that, when not specically underlined, the programming interfaces for the application level developers will remain unchanged. The term binary compatibility (BC) indicates the possibility of running the same program binaries on different machines. Backward compatibility indicates a situation where a client software built against an old version of the library can run against a new version of the library. Forward compatibility, in contrast, is satised when client built against a new version of the library can run against an old version of the library. As an example, consider the situation where some Series 60 licensee develops a new smartphone with additional functionality and makes the new application programming interfaces available to third-party developers. The new smartphone is backwards compatible, because Series 60 applications engineered for, for example, Nokia 7650 still run on the device. However, it is not forward compatible, because the applications created by third parties that take advantage of the new application programming interfaces (APIs) will not run on the Nokia 7650 smartphone. Thus, if full BC is desired, the new interfaces may not be made available to third-party developers.
294
The Series 60 Platform requires customization for the devices within which it is used. This was the case even in the very rst Series 60 device: the Nokia 7650. The Series 60 Platform has a certain UI style in it that the licensee will then change to suit a companys branding. The underlying hardware can change. The computer processing unit (CPU) can at least, in theory, be different from the recommended 32-bit ARM processor (e.g. M-Core, or Intel). Peripherals can denitely change, new devices not supported by the Series 60 Platform can be introduced (e.g. a camera), and the peripherals can simply have a different chip from the those supported by the licensed code.
295
resources. Changes to the LAF module do not affect external APIs, because only a limited number of classes link to the UikLAF.dll that contains the implementations of the various look-and-feel classes. The adaptable core consists of multiple libraries. Most of these libraries contain a set of classes implemented for a limited purpose. These libraries include: EikDlg.dll, which contains the dialog framework classes; EikCtl.dll, which contains common controls; EikIr.dll, which contains infrared dialogs; and EikFile.dll, which contains the le-handling dialogs and controls. These libraries cannot be modied in any way; the adaptable nature of this module comes from the device manufacturers being allowed to remove whole libraries. For example, the Series 60 Platform does not reveal even the existence of the le system to the user and therefore the EikFile.dll can be removed to save ROM. Application modications are an important part of the UI customization. These do not usually require skills outside of normal application development. The most common examples of this category are the addition of new applications and modications to existing applications. New applications can be branding, for example Nokia could add a snakes and ladders game to the application set. Some of the applications are there to increase the fun, games, and other entertainment applications, or to provide tools such as the currency converter. Yet another reason for new applications are the addition of new peripherals such as the camera and photo album applications on the Nokia 7650. Modication of existing applications will in most cases consist of changes to the appearance. The basic set of applications is expected to appear on each Series 60 device, and the third-party developers can, for example, expect to nd a phonebook application on the device with a view to enter a new contacts information. If the phonebook application were modied incorrectly, it could result in application inoperability on that device. Other changes to views may consist of changing the normal navigation order, layout of the controls, and so on. Two examples of modules that can be modied requiring skills not generally asked of application developers are status pane modications and notier framework changes. Both can be modied in a relatively short time but require the use of frameworks not accessible, except for the ROM build.
296
60 graphical user interface (GUI), Avkon, has its own LAF module that needs to be modied as well. The Series 60 LAF module is implemented in a similar way to the Uikon LAF module; however, certain additions have been made to the Uikon LAF module. These additions extend the possibilities of inuencing the look and feel of the controls, not to change the core possibilities. The extensions include more ways to affect Edwins and other controls and the way in which they draw themselves in the Series 60 Platform. Again, in theory, it would be sufcient to modify the Uikon LAF with Avkon extensions, but, unfortunately, the drawing and behavior of the controls are actually spread in more locations than only the LAF modules. The most common places to nd these areas are (1) the class for the control itself and (2) one of the parent classes for the control. Changing the implementation of a class outside the LAF modules can be tricky. Modications to a class that is derived by multiple classes naturally affect all the deriving classes and may result in more problems than solutions. Making changes to the class itself may require removing some of the functional dependencies in the inherited classes as well as the LAF modules. After those changes, further modications intended to modify the UI appearance are even more difcult with the decreased portability. In practice, not just in theory, most of the modications to the look and feel can be made by modifying the LAF modules but not all such modications. As mentioned above, the LAF modules offer static classes where the individual controls can get, for instance, margin width, colors, etc. In most cases, the application developers should not be concerned that there is a varying look and feel that the application can conform to each devices style. The Series 60 LAF module includes a class that should also be used by application developers: AknLayoutUtils. This class offers a way of laying out controls to the screen and allowing them to adapt to the current devices way of displaying each control. Addition of controls is done by using functions such as LayoutLabel(), LayoutEdwin(), and LayoutControl(), which are able to read the proper text margins and borders, and so on.
297
Figure 14.2 Application shell in (a) grid and (b) list format
any other application; its task is to show the user which applications are present in the device and a means of navigating and managing the applications. Managing the applications is done by organizing the applications in folders, by type. How the applications are shown to the user makes a big difference; the Series 60 Platform provides two possibilities for the appearance of the application shell to the user: a grid and a normal list, shown in Figure 14.2.
14.1.3
Status Pane
The status pane, shown in Figure 14.3, is an uncommon control in Symbian OS in the way that it is owned partially by the Eikon server and partially by applications or other status pane clients. The status pane is divided into subpanes by dening the status pane layouts as discussed in Chapter 9. The available layouts of the status pane and the subpanes that can be modied by the application developers are dened at ROM build. The status pane is typically used to display both system information in the
298
system-owned subpanes and application-specic information in the application-owned panes. Typical system information includes icons for the signal and battery strength. Application-specic information includes the application name and the icon. Customizing the status pane is done by modifying the available layouts, or by dening new ones, and then modifying the individual controls in the panes. It should be noted that application developers are allowed to assume a certain level of consistency across various Series 60 devices and that the possibilities are limited when making changes to application-owned panes. The status pane layouts are dened in avkon.rss with the resource type STATUS PANE LAYOUT. The layouts in Nokia 7650 are usual layout, idle layout, and power-off recharge layout. Each layout denition is formed by dening the position of the status pane (e.g. vertical pane on top of the screen) and the panes themselves. The pane layout is organized as a tree with SPANE LAYOUT TREE NODE resource denitions. Each denition can have the following elds: size: the width or height in pixels; which is specied depends on the tree node; the status pane is vertical then the top level size denes the height, the second level size denes the width, and so on; subpanes: each subpane consists of a number of SPANE_LAYOUT_ TREE_NODE denitions; ID: the identier (ID) for the subpane must be one specied in the system model; ags: these are most often EEikStatusPaneIsStretchable if the size is not xed; in most cases the ags are omitted. Laying out each individual subpane can be a tedious job, especially if some of the panes are stretchable. Each pane needs to be specied in terms of pixels, and it should be considered that, at this point, the appearance of the controls will be xed. Most of the controls in the status pane are displayed by bitmaps, and the graphical outlook of a signal strength, for example, can be rather tightly xed by the company brand. The controls, however, are not tied to each pane with the layout structure but with a status pane model common to all layouts the status pane system model. The controls that occupy each subpane are specied in the system model of the status pane. The system model is dened with the resource denition STATUS PANE SYSTEM MODEL. Most of the denitions are formed by a list of individual pane denitions of type SPANE PANE. In addition, the system model species the default layout and also lists
299
all the available layouts. Each SPANE PANE resource is dened using the following elds: ID: the id used by the layouts; if the ID is not present in the layout used, then the control is not shown; ags: mostly for specifying whether the pane is system-owned or application-owned; the default value is server-owned; type: the type of the control (e.g. EAknCtSignalPane); resource: the resource denition for the control. The control is specied in the SPANE PANE resource, just as it would normally be dened in the resources. It is also quite possible to dene multiple panes with the same control. This will be the case where the control itself cannot adapt itself to different sizes, but will, for instance, simply draw the bitmaps associated with the control. In such cases, a simple solution is to provide multiple sets of bitmaps and dene multiple sets of status pane denitions, where the initialization of the control would differ by the le from which to read the bitmaps.
14.1.4
Notiers
The notier framework is a means for the system to notify the user, in multiple ways, of events, regardless of the current active application or the systems state. The framework is based on events and channels. A simple reason for a need to modify the existing implementation is that the device includes a way to notify the user not present in the original Series 60 Platform implementation. An example of this type of extension would be to ash an LED (light-emitting diode) when there is an incoming phone call. Series 60 has a set of channels that can be extended with new channels, if the device manufacturer wishes to do so. There can be multiple events at the same time, and each event can use multiple channels in informing the user about the event. The events can be specied by the device manufacturer, but they usually follow a common line. Typical events include an incoming phone call, a new message in the inbox, and battery low. Each event can be notied to the user by using multiple channels (e.g. the phone call can start a ring tone, an LED ashing, a vibrating battery, and a dialog on display). Looking at the list of typical events, it is easy for one to conclude that certain events are more important than others. Therefore, the events can have priorities for each channel, and the order of the priorities can change between the events, depending on the channel. For example, for the loud speaker, the incoming phone call may have a higher
300
priority than the battery-low signal, but on the display the battery-low indication may be on top of the phone call indication. In Symbian OS v6.0 the notier server supports plug-in notiers. These notiers can then be started and cancelled according to their unique identier (UID). The notiers are tied to a channel with a priority, and show the information passed by the client. The API for starting the notiers is dened in the class RNotifier that is the client interface to the notier server. The notication is started synchronously with StartNotifier() or asynchronously with StartNotifierAndGetResponse(). If the notication needs to be changed (e.g. the text in the dialog is updated) then the UpdateNotifier() can be used. The text might be there to give some additional information about the severity of the notication (e.g. the estimated amount of battery life left in the device). Notiers can be implemented in several ways. For example the StartNotifier() function, which applications will call directly without an updating possibility, can be used; alternatively an observer framework, where the application would be notifying the notier about changes to its state, can be provided, leaving it up to the notier to decide what to do in each case.
BASE PORTING
301
ASSP port as the starting point, as adding the rest of the peripherals and possibly modifying something in the existing ASSP port. The next level in difculty to an ASSP port is a CPU port, where CPUlevel implementation is done. Development of a CPU port is, however, something that is normally left to Symbian. It is recommended that Series 60 devices have a 32-bit ARM (Advanced Risk Machines) processor and thus there is no need for a CPU port. The structure of the kernel is also supported on these various levels of porting. The Symbian OS kernel has, in fact, four layers (Figure 14.4):
Euser Kernel Independent Platform CPU ASSP Variant Emul Win32 ARM 710 CL7210 ARM SA 1100 Assabet Ekern EPOC MCore LDDs
PDDs
CPU = Central Processing Unit ASSP = Application Specific Standard Port ARM = Advanced Risk Machines (ARM is the well-known term, not the full term) LDD = Logical Device Driver PDD = Physical Device Driver Other terms should not be given in full, because these are the standard used abbreviations.
Figure 14.4 Kernel modules and layering, with a few linking modules outside the kernel
The independent layer is the interface to the kernel. All the modules linking to the kernel should link to the classes dened in this layer. The independent layer is common to all Symbian OS builds. The platform layer has two subpaths: emul and EPOC. The emulator uses the former, whereas all the target builds use the latter version of the platform. Most of the logical device drivers reside at the platform layer. At the CPU layer, the Symbian OS kernel is split between CPU (e.g. ARM, M-Core, and Intel). Scheduler and interrupt handler can be implemented at this layer. The ASSP layer separates, for instance, the various ARM implementations from each other. Some of the physical device drivers are implemented at this layer.
302
In addition to the layers, there is the variant. All the peripherals are added at the Variant level, and most of the physical device drivers are implemented at this level. Let us assume the ASSP used is already supported and that variant port is the one required. The required steps are described next. The rst thing to do is to get the code running on the device. If the already-supported methods cannot be used (e.g. JTAG) then they need to be modied or a new method needs to be implemented. Once the image is on the device, it needs to be started, and for this the bootstrap may need changing (e.g. to support a different RAM layout). After this, it is time for the actual variant code changes (i.e. variant DLLs and device drivers). In particular, if the required screen (176 208 screen with recommended 0.2 mm pixel size) is not supported, the display driver should be one of the rst drivers to be implemented. The basic initialization is already done during the ASSP port, and the variant port should aim at having the text shell running at a very early phase. Once the text shell is running, the kernel tests can be run and benchmarked, the rest of the device drivers be implemented, the power model ne tuned, and so on. After the base porting part is nalized, the text shell can be replaced by the full GUI image, and at this point the storage memory requirements come to the normal gures in a Series 60 device (i.e. approximately 16 MB ROM and 8 MB RAM). The GUI can be customized at this point, since the only thing it links to that may be changed during the base port are the new device drivers (e.g. camera drivers in the Nokia 7650). In addition to changing the GUI and the variant, it may be necessary to modify some of the system server functionality, typically by adding or modifying the plug-in modules. One very important example would be to modify a telephony module to support underlying telephony implementation outside Symbian OS. These modules are known by their le extensions: .tsy. Implementing a proper .tsy plug-in can be considered one of the major tasks in creating a Series 60 device. Again, the details are beyond the scope of this book, but for a general explanation of .tsy modules see Chapter 15.
303
required but rather will try to get an overall picture and cover the main tasks. The details can be found in relevant chapters elsewhere in this book. The application model should have been written using generic APIs of Symbian OS only, which should not have to be changed unless the changes between versions require it. Main tasks outlined here are (1) functional changes, (2) UI changes, and (3) changes to communications.
304
be changed might be easier to implement from scratch than to use old application as the base.
Application Framework
The Series 60 Platform has implementations for all four basic classes used in the application: application (CAknApplication), document (CAknDocument), application user interface (CAknAppUi and CAknViewAppUi), and view (CAknView). In the simplest form of application porting, the application UI class must be made to derive from CAknAppUi. Other derivations are changed if needed. The implementations of the classes may not have to be changed. The resource le needs a small change to EIK APP INFO and the menu denitions. The menu denitions are changed to follow the specications found in, for instance, the Nokia Series 60 UI Style Guide (Nokia, 2001g). The EIK APP INFO is typically as in the rockpaperscissors (RPS) game (see Chapter 8), with only the menu, and the command button array (CBA) with one of the Series 60 readydened softkey pairs. In addition, you need to remember to react to the EAknSoftkeyExit command in the HandleCommandL() function:
RESOURCE EIK_APP_INFO {
305
If the application uses dialogs, and most do, then the dialogs must in most cases be reimplemented. This applies even to simple information dialogs launched by the Eikon environment, and notes should be used instead; for example, CEikEnv::InfoWin() is not present in Series 60, and CaknInformationNote, for example, should be used. The default implementation may lead to nonmanageable results, as shown in Figure 14.5. The dialog ported is a multipage dialog with a numeric editor as one of the controls. As Figure 14.5 shows, the tabs are hidden whenever, for instance, the numeric input icon is shown in the status pane; also, the prompt in front of the eld does not show the text properly. The dialogs should be implemented so that each item is visible; but, for editing, a popup eld is opened. Using the Series 60 query dialog framework produces this effect automatically.
Figure 14.5 A badly implemented multipage dialog with a numeric editor eld focused
The Series 60 application view implementations fall roughly into three categories: control views, dialog views, and view architecture views. The rule of thumb in porting is: use the one used in the original implementation. In practice, this refers to the control views in most cases. The dialog views can especially be used if the original view needs to be split into multiple parts that may need editing, and the views and navigation between them are like dialogs. The Series 60 standard applications include many examples where the main view is, in fact, a list of dialog pages, and the second view is a multipage dialog. View architecture is new to Symbian OS v6.0 and obviously is not used in ER5; Nokia 9200 series does not include many applications using view architecture, but UIQ does utilize the view architecture in many of its applications. The bad news for those wishing to port view architecture views to Series 60 is that there is another architectural layer in Series 60 on top of the Uikon view architecture. Therefore, porting an existing view architecture view structure may not be as easy as it might be expected to be. An application that originally used control views can, of course, be changed to use the view architecture, especially if there are many views and those views may want to pass data to each other including between views from different applications. If the solution is made to
306
use the view architecture, it is time for a session of very creative copy pasting. The application user interface is changed to derive from CAknViewAppUi, and much of its implementation is stripped and moved to the views. It is possible that the application user interface does not own a single view or a menu and it may handle only one EEikCmdExit command in its HandleCommandL() function. Each view typically has its own menu and command handling, and the views are owned by the view server. In addition, the navigation must be decided on, keeping in mind that the view activation is an asynchronous call to the view server, and the application does not have any way of telling whether the activation has actually succeeded.
14.4 Summary
In this chapter we have discussed application porting and platform customization of the Series 60 Platform. The customization may involve three tasks: UI customization to create a certain branch of the device, base porting to port Symbian OS base to new hardware, and telephony system integration to enable communication between the cellular phone system and Symbian OS. Application porting involves three tasks: functional changes, UI changes, and changes to communications.
Part 3
Communications and Networking
15
Communications Architecture
The microkernel structure of Symbian OS has an effect on its communications architecture. Communication services are used through system servers, which may be added or omitted, depending on the communication hardware supported by the smartphone. Communication software is implemented with plug-in modules used by the servers. New modules can be deployed and unloaded without restarting the phone. This allows an easy way to extend and congure the phone with respect to changes in the environment when, for example, the user is roaming into a new location. This chapter contains a description of the communications architecture used in the Series 60 Platform. The architecture species the structure, interfaces, and behavior of communication software. It is based on Symbian OS v6.1, the Series 60 Platform consisting mainly of user interface (UI) libraries. The architecture builds up from communications servers and plugin modules. Servers provide basic communication services with the aid of technology and protocol-dependent communication modules. When a new service is required, a new module may be implemented and loaded to the memory without rebooting the device. Unnecessary modules may also be unloaded to save scarce memory resources. In addition to servers and communications modules, the most commonly used communications technologies supported by the Series 60 Platform are covered in this chapter. Two following chapters provide examples on how to use communication services in applications.
15.1
310
COMMUNICATIONS ARCHITECTURE
Protocol implementation layer MTM module PRT module TSY module CSY module
Physical layer
Figure 15.1 The communications architecture of Symbian OS. Note: CSY module, serial communications module; MTM, message-type module; PRT module, protocol module; TSY module, telephony control module
the well-known OSI (open systems interconnection) reference model, is the protocol implementation layer. There are four servers that can be involved in protocol implementation, depending on the characteristics of the protocol: Serial comms, Socket, Telephony, and Message server. Each server uses polymorphic interface libraries or plug-in modules that implement a specic communication service or protocol.
311
typically contain one R-type class derived from the RSessionBase class, which provides a handle to a server object in another process. This handle is used to create a session to the server (eventually, the RSessionBase::CreateSession() function is called) and query information, such as the number of supported serial ports or protocol modules, from the server. The set of supported functions in the API is quite similar in separate comms servers, which makes it possible to dene an abstract class to be used with any server. The API also contains one or more classes derived from RSubsessionBase, which provide functions for creating subsessions (typically, opening ports, sockets, or calls) and for transferring the actual data (taken care of by the SendReceive() function in RSubsessionBase). There are four communications servers in Symbian OS: the Serial communications server (C32), which provides a generic interface to serial-type communications; the Socket server (ESock), which provides a generic interface to communications protocols through communication endpoints known as sockets; the Telephony server (ETel), which provides a generic interface to initiate, control, and terminate telephone calls; the Message server, which provides access to message data and to the server-side message-type modules (MTMs). In Figure 15.2, the servers and their users are depicted. In addition, some additional communications components, such as Communications database and protocols, accessed by the Socket server, are shown. The use of communications servers depends on the application. Applications requiring simple bit transfer services need to use only simple serial-based communications, in which case the Serial comms server provides the service. The Serial comms server uses a protocoldependent serial protocol module having a lename extension. csy. There is a separate module for RS-232 and infrared protocols. The CSY (serial communications) module uses device drivers in the kernel to access the communication hardware. Also, the device drivers are plug-in modules, which may be loaded and unloaded with respect to the hardware conguration in different locations. Applications requiring more advanced services can use one of several available protocols for this purpose at the protocol implementation layer. The application may use the servers directly. However, it is more common that the application use a client API of one server, which may then use other servers, if required by the protocol. For example, the wireless application protocol (WAP) suite uses a WAP
312
COMMUNICATIONS ARCHITECTURE
Application
MTM UI
Messaging client
Messaging server
Telephony server Comms engine Connection agent Serial comms server Internet protocols
Comms database
Sockets server
Device drivers
Hardware
Bluetooth protocols
Figure 15.2 Communications (comms) servers. Note: MTM, message-type module; UI, user interface
module to access the WAP stack, which uses the short message service (SMS) protocol module to use SMS as a bearer. The SMS protocol module uses the GSM (global system for mobile) telephony control module to send the SMS over the GSM network. At the bottom, the telephony control module uses a serial protocol module to control the smartphone. All plug-in modules supply a single, unied interface in the form of a polymorphic interface dynamic link library (DLL). This enables several implementations of the same module, each capable of interfacing with different communications hardware and software. Communications plug-in modules are used in the implementation of communication protocols. Layers of the same protocol may be implemented in separate modules. For example, physical and data link layers become part of the serial protocol module (or even device drivers), and the network and upper layers become part of
313
the socket protocol module. The set of available plug-in module types include: the logical and physical device drivers used to abstract the hardware from software modules; the serial protocol modules used by the Serial communications server; the protocol modules and connection agents used by the Socket server; the telephony and modem control modules used by the Telephony server; the message-type modules, used by different message types and messaging objects.
314
COMMUNICATIONS ARCHITECTURE
Application
ecuart.csy
ircomm.csy
btcomm.csy
ecomm.ldd
ecomm.ldd
ecomm.ldd
euart1.pdd
euart1.pdd
euart1.pdd
Figure 15.3 Use of device drivers and communication modules with RS-232, infrared, and Bluetooth
comms is implemented by the RDevComm class, which provides a handle to a channel to the serial device driver. However, instead of using RDevComm, the client-side should interface to the Serial comms server through the RCommServ class, the API of which is described in the next chapter. Depending on the requirements of the application (and the characteristics of the smartphone) the Serial comms server uses either RS-232, infrared, or Bluetooth serial protocol module. Other modules can be implemented if new hardware interfaces are developed. Typically, clients need no knowledge of the individual CSY modules available in the phone, since they ask the Serial comms server to load whichever is dened as active in the Communications database. The Communications database will be discussed in more detail later in this chapter (Section 15.1.3). All communication modules in Symbian OS are polymorphic interface libraries and are thus implemented according to the same principles. CSY modules are identied by the second unique identier (UID), the value of which must be 0x10000049. A CSY module has three concepts that the developer of the module must implement: serial service provider (CPort class), serial protocol factory (CSerial class), and serial protocol information (TSerialInfo class). Thirdparty software developers do not usually implement serial protocol modules, and this is why the implementation details go beyond the scope of this book.
315
Protocol Modules
Protocols are used to add value to communication on top of unreliable and inefcient (in terms of channel utilization) serial-based data transfer. Added value can be, for example, error detection and correction methods, efcient and adaptive ow control, ability to avoid congestion, support of multiple simultaneous connections, or support of multipoint connections. Most protocol implementations are accessed in Symbian OS through the Socket server, ESock, which provides a similar interface to that of the well-known BSD (Berkeley Software Division) sockets. This guarantees transport independence; that is, whatever the used protocol is, it may be accessed through the similar client-side API of the Socket server. Higher-level protocols (from network to application layer) and protocol suites consisting of several protocols are implemented in plug-in modules, called protocol modules, having an extension. prt. Example protocol suites supported by the Series 60 Platform include TCP/IP (transmission control protocol/Internet protocol; tcpip.prt), IrDA (irda.prt), Bluetooth (bt.prt), and WAP (wapprot.prt). All protocols are loaded and accessed by the Socket server and accessed through a similar client-side API, regardless of their specic properties, as shown in Figure 15.4. Thus, they all have common networking operations such as sending and receiving data, establishing connections, and conguring protocols, but their implementation may be completely different. When using TCP, conguration requires binding (or connecting in the client) to a specic port in the specic IP address, whereas in IrDA and Bluetooth, conguration requires device discovery to nd another device with which to communicate.
Application
Socket server
tcpip.prt
irda.prt
bt.prt
Figure 15.4 Use of protocol modules through the Socket server. Note: API, application programming interface; DLL, dynamic link library
316
COMMUNICATIONS ARCHITECTURE
When the Socket server is started, it scans for the esock.ini le to nd out which protocols and services are dened in the system. A protocol module is loaded when a socket belonging this protocol is opened. It is also possible to load and unload protocol modules beforehand to decrease the delay during opening. In addition to connections to other devices, the Socket server provides access to other network facilities, such as host-name resolution, service resolution, and network databases, the use of which depends on the protocol. In the next chapter we will give numerous examples of the use of these services. Since Series 60 smartphones have no permanent connection to the Internet, one must be established before transmitting or receiving any data. For this purpose connection agents (e.g. genconn.agt) are used. The connection agent obtains the current default Internet access point (IAP) settings from the Communications database and uses telephony control modules to dial up and establish a call to an IAP in case a circuit-switched data (CSD) service is used. If the General Packet Radio System (GPRS) is used instead of CSD there is no need to create a connected call. New protocol modules may be created by system developers if new protocol standards are developed. The implementation consists of three concepts: a protocol family, a protocol, and a socket. All protocol modules are polymorphic DLLs, the second UID of which is 0x1000004A. The base classes corresponding to the three concepts are CProtocolFamilyBase, CProtocolBase, and CServProviderBase, dened in es prot.h. A protocol module can contain one or more protocols, in which case it is called a protocol family. A protocol family may build up the whole protocol suite or be a part of it, in which case functions in one protocol module may call functions in another protocol module. All protocols inside a family must be able to identify themselves and their capabilities, and at least one protocol in a family must provide socket services through the Socket server. Individual protocols inside a protocol family are dened in an *.esk le in the system\data\ folder. The tcpip.esk le is shown below as an example. The NifMan (network interface manager) is used to start up the network interface (data link connection) and monitor the progress of connection establishment:
[sockman] protocols= tcp,udp,icmp,ip [tcp] filename= TCPIP.PRT index= 4 bindto= ip,icmp [udp]
THE BUILDING BLOCKS OF THE COMMUNICATIONS ARCHITECTURE filename= TCPIP.PRT index= 3 bindto= ip,icmp [icmp] filename= TCPIP.PRT index= 2 bindto= ip [ip] filename= TCPIP.PRT index= 1 loopback= loop0 [nifman] default= genconn
317
CProtocolFamilyBase provides functions to list and get protocols from a protocol family. CProtocolBase is used to implement a socket, host-name resolution, service resolution service, or access to a network database. The class also has functions that the upper-layer protocols can use to bind to the protocol. The protocol module must contain a socket implementation derived from CServProviderBase for each protocol, which supports sockets. Socket implementations use the MSocketNotify interface to inform the Socket server about events.
Message-type Modules
Message-type modules (MTMs) implement message-handling functions. Message handling includes creation, sending, receiving, and editing messages. For each message type a separate message-type
318
COMMUNICATIONS ARCHITECTURE
module is required. It is possible to install new MTMs dynamically to the phone. New MTMs are registered in the MTM registries. Messaging applications check from the registries the set of available MTMs in the system. Existing MTMs enable the handling of e-mail messages (SMTP, POP3, IMAP4; see the Glossary), faxes (in the Series 60 Platform, fax support is limited to fax modem functionality), short messages (short message service, SMS) or multimedia messages (multimedia message service, MMS). There is not only one MTM per message type, but four: clientside MTM, user interface MTM, UI data MTM, and server-side MTM. In addition, there are four registries, holding records of each installed client-side MTM, server-side MTM, and so on. Every MTM is implemented as a polymorphic interface library, like any other communication module. The client-side MTM interprets the contents of a message and provides a minimum set of generic functions. One function that is always available is Reply(). Using Reply() it is easy to implement a consistent user interface for replying to any message regardless of its type. The UI MTM provides editors and viewers. The UI data MTM provides services, which are applicable more universally. This MTM uses the message identier to recognize the message type. Using the type the message can be shown to the user correctly without loading the UI or client-side MTMs. Thus, UI data MTMs provide universal message folders capable of storing any type of message. In addition, they are memory-efcient as the load of other MTMs may be avoided. The server-side MTM takes care of message formatting and transferring. The role of the Message server is different from that of the other three communication servers, described above. It does not provide an API through which the services of MTMs are used. Rather, client-side MTM and UI MTM may use the server, which then uses the server-side MTM to complete the service. The Message server also has a message Index, in which each message has a UID. In addition to the identier, the Index information includes the description of the message (header), the size of the message, and a ag indicating whether the message has attachments of binary information in le stores. The relationship of the Message server and message-type modules is shown in Figure 17.1 (page 376). The simplest way to allow applications to create outgoing messages is to use the CSendAs class. It allows applications to package data into a message without using the MTM interfaces directly. An object of type CSendAs creates a session to the Message server, and the object can access the client-side MTM registry to get available client-side MTMs and the set of services they provide.
319
320
COMMUNICATIONS ARCHITECTURE
One of the rst things to be done is to create a session to the specic comms server. After that a communications channel (port, socket, line, call) is opened, which typically means the creation of a subsession to the server. Communications settings have to be provided, after which it is possible to transfer data. Finally, subsessions and the session (connection) must be closed. More through investigation reveals the following actions must be done (here, we follow the ve phases presented in Jipping, 2002): initialization: load required device drivers, start the communications server(s) (if not already running), and connect to it (i.e. create a session to it); load required communications modules if this is not done automatically; open: open the subsession (typically, open a port or a socket); depending on the server this may involve dening, for example, the access mode (exclusive or shared) or communications mode (connection-oriented or connectionless); conguration: set up parameters for communication, for example, baud rate or role (client or server) and undertake device and service discovery if required; data transfer: transmit and receive data; close: close handles to subsessions and session to release allocated resources. Depending on the server and communication modules used, there may be other phases or states as well. For example, use of a connectionoriented protocol requires three phases: connection establishment, data transfer, and connection release. Data calls have possibly even more states, such as service and location selection, dialing, script scanning, login information fetching, connecting, data transfer, and hanging up. The ve states mentioned above are repeated in all comms servers except in the Message server. To make communications programming easier, we can dene an abstract class having functions that relate to the identied ve phases. In the next chapter we will see how this class is used in the implementation of comms classes in our application. This kind of denition is also presented in Jipping (2002). First, we dene the class to be an M class, so it provides only virtual functions that are implemented in the concrete class:
class MCommsBaseClass { public: virtual void InitializeL()=0;
SUPPORTED COMMUNICATIONS TECHNOLOGIES virtual virtual virtual virtual virtual } void void void void void OpenL()=0; ConfigureL()=0; Transmit( TDesC& aTransmittedData )=0; Receive()=0; Close()=0;
321
The concrete class is typically derived from CActive, so it is an active object. This is because both receiving and transmitting are asynchronous services in Symbian OS. The Initialize() function may leave if it cannot load the requested device drivers and communication module. Open() leaves if the subsession to the server cannot be created. A common reason for failure here is that the session has not been properly created earlier. The programmer has not detected the failure, because the return value of the Connect() function has not been checked. The ConfigureL() function depends much on the server used. Sockets do not require much conguration, but there are several parameters related to serial ports. Transmit() and Receive() functions call the corresponding functions in transmitting and receiving active objects, which issue asynchronous service requests to the server (actually, it is often possible to use the synchronous versions of the functions to issue service requests, but this is not so common). The received data are typically stored in a member variable of the receiving active object. After the receive request has been completed, the RunL() function of the receiving active object is called. The active object noties its observer (typically, a view) to read the received data. Examples of implementing this functionality will be given in the next chapter. The Close() function closes the handles to subsession and session. If Close() is not called, the handle remains open and there exist useless allocated objects in the server which consume memory unnecessarily. If the handle is not closed it will be closed when the thread dies and all resources allocated in the thread are freed. The Close() function is typically called in the DoCancel() function, which in addition to closing cancels all uncompleted requests.
15.2
322
COMMUNICATIONS ARCHITECTURE
Note that a smartphone based on the Series 60 Platform does not have to provide RS-232 port, although the OS supports it. For example Nokia 7650 has no RS-232 port. Web and WAP browsing are supported on different bearers (SMS, CSD or GPRS). Data can be synchronized and converted between applications in the smartphone and desktop computer using the connectivity framework and SyncML protocol.
323
primitives are available in the SAP (service access point), which is an identier (address or port number) of the service provider protocol. In Symbian OS, higher protocol layers are implemented into protocol modules; lower layers may be part of the serial protocol module. The implementation details of a protocol are hidden from the user, who sees only the client-side API of the Serial comms or Socket server. Although, a protocol may provide an arbitrary number of services, there are only four service primitive types. Unreliable service requires only two primitive types: request and indication. The former is used to request the service, and the latter indicates that a peer entity has requested a service. The other case is reliable, where the service is conrmed with two primitive types: response and conrmation. The response is issued by the entity that received the indication to give information about the success of the service request. Finally, this information is passed to the original service requester by the conrmation primitive. All protocol denitions include the denition of messages and service primitives. However, the user of a service API of Symbian OS has no idea about the underlying service implementation or service interface because she or he always accesses the service through a certain communications server.
15.2.2 RS-232
RS-232 is a simple point-to-point protocol supporting both synchronous and asynchronous communication, where data are transmitted serially one bit at a time. Synchronous transfer is faster but requires clock synchronization; asynchronous transfer requires only that the same baud rates are used in the transmitter and the receiver. Although synchronous transfer is faster, it is used very seldom. Data are transmitted inside frames that consist of 58 data bits. Other bits are used for indicating the start and stop of transmission (in asynchronous communication), and error detection (parity bit). The frame structure is shown in Figure 15.6.
Start bit 1 Data 101010 Parity bit 1
A single parity bit indicates whether the number of 1 bits is even or odd in the code word (data frame). If one bit is changed in the code word, the parity bit changes as well, which increases the minimum distance between code words (the hamming distance) from one to two.
324
COMMUNICATIONS ARCHITECTURE
If the Hamming distance is n, it is possible to detect all n 1 bit errors (Stallings, 1999). Thus, a single parity bit is capable of detecting one-bit errors in data frames. Two-bit errors cancel out and cannot be detected at all. Three-bit errors are interpreted as one-bit errors, and so on. For ow control there are two options in RS-232: software handshaking, based on XON and XOFF signals, and the more complicated hardware-based handshaking, based on clear to send (CTS) and ready to send (RTS) signals. XON simply indicates that the receiver is ready to receive data, and XOFF indicates the transmitter is to seize up until XON is received again. Hardware handshaking is much more complicated. CTS is used by the receiver to indicate that it is ready to receive data. The transmitter uses RTS to request a data transmission, but before any data are transferred data set ready (DSR) and data carrier detected (DCD) signals must be set too. DSR indicates that the carrier (e.g. a modem) is ready, and DCD that the modem has a good carrier signal. Thus, all signals (DSR, DCD, and CTS) must be set before the transmission takes place.
15.2.3
IrDA
IrDA (infrared data association) is not a single protocol but a protocol stack that hides the physical characteristics of infrared (IR) communication. So, IrDA is not implemented in the serial protocol module but as a Socket server protocol module in Symbian OS. The stack is depicted in Figure 15.7. Framing, taking place at the physical layer and controlled by the IrLAP (infrared link access protocol), is more complicated than in RS-232. Seven-bit start and stop sequences are used, and multibit errors in one frame can be detected with the cyclic redundancy check (CRC) method. Using the method, a transmitted frame is divided with a
IrLAN IrObex IrCOMM IAS TinyTP IrLMP IrLAP
Physical layer
Figure 15.7 The IrDA (infrared data association) stack. Note: IAS, information access services; IrLAN, infrared local area networks; IrOBex, infrared object exchange; IrCOMM, serial communication server; TinyTP, tiny transport protocol, IrLMP, infrared link management protocol; IrLAP, infrared link access protocol
325
generating polynome (bit sequence) and the remainder of the division is added at the end of the frame. The receiver divides the received frame together with the received remainder with the same generating polynomial used by the transmitter; if the remainder is zero, the frame is received correctly with high probability. IrLAP (infrared link access protocol) provides the reliable transfer of bits over physical media. Reliability is achieved with the CRC method, simple media arbitration, acknowledgements, and retransmissions. The arbitration method is very simple. A device that is not transmitting must rst listen to the media for 500 ms and establish a connection after that, provided there are no other devices transmitting during the listening period. After the connection has been established, it is active until disconnected. Connection is always established by using the same conguration:baud rate of 9600 bps (bits per second), eight-bit frames, and no parity. After the connection establishment, the devices negotiate the conguration parameters. IrLAP also addresses each datastream, so there may be several logical connections over one physical IR link. There are three different framing methods dened: asynchronous SIR (slow IR), from 9.6 to 115.2 kbps; fast IR (FIR) with synchronous SDLC-like (Synchronous Data Link Control) framing from 57.6 kbps to 1.152 Mbps; FIR with synchronous pulse position modulation (PPM) up to 4 Mbps. IrLMP (infrared link management protocol) is responsible for connections between applications (link multiplexing, device discovery). Each datastream is assigned with a one-byte number, which is a logical service action point (SAP) selector. The communication process has the following phases: Device discovery : exchange of information with IrLMP peer entity to discover information about the device; connection: data connection with service IDs; data delivery: exchange of application data; disconnection: close of IrLMP connection and resetting the service IDs. Service IDs are recorded into an information access service (IAS), which is a network database accessible through the Socket server. This enables several services to share the same IR link. TinyTP (tiny transport protocol) is an optional protocol in the IrDA stack but is included in Symbian OS. It is responsible for ow control
326
COMMUNICATIONS ARCHITECTURE
and data segmentation and reassembly. Each IrLMP connection may be controlled individually, which enables efcient ow control and link utilization. The size of the service data unit (SDU; i.e. the data frame) is negotiated with the IrLMP. Datastream is segmented into SDUs, and each SDU is numbered. This enables efcient interleaving of the IR link. In addition, errors affect smaller data units, which improves the efciency of data transfer. IR programming APIs are shown in Figure 15.8. It is possible to use the client-side API of the Serial comms server (IrCOMM), in which case an IR link is emulated to be an RS-232 link. The IrDA protocol is accessed through the Socket server. There are two services: the IrMUX and TinyTP protocols. In addition, it is possible to use the IAS. IrTinyTP provides a reliable transport layer, which corresponds to a sequenced packet service, while the IrMUX protocol corresponds to unreliable datagram service. Note that IrCOMM provides only a xed data transfer of 9600 bps. Other services, such as IrObex (infrared object exchange) and IrLAN (infrared local area network), uses IrMUX or TinyTP. For example, IrObex uses IrMUX in port numbers, dened in the IAS.
Application
Socket server
IrCOMM
IrMUX
IrTinyTP
Figure 15.8 Infrared programming application programming interfaces (APIs). Note: IrCOMM, Serial communications server; IrMUX, protocol corresponding to the unreliable datagram service; Ir Tiny TP, infrared tiny transport protocol
15.2.4 mRouter
The mRouter protocol has replaced the psion link protocol (PLP), which was used to synchronize and convert data between the smartphone and desktop computer. The protocol may use either TCP, UDP(user datagram protocol), or IP on top of the point-to-point protocol (PPP) link to enable data transfer between the PC and the smartphone. In addition, the protocol may be used, as the name indicates, as a gateway allowing the smartphone to access Internet through the PC. The mRouter protocol is described in more detail in Chapter 18.
327
15.2.5 SyncML
SyncML is a standard for universal device synchronization and device management. It enables the use of one program to synchronize several devices and use networks as well as serial cables on multiple platforms for synchronization. The SyncML server is a device containing a sync agent and sync engine. The SyncML client rst sends its modications to the server. After receiving the modication, the server does sync analysis to check which information has changed. After client modication, the server may send server modications to the client to complete the synchronize procedure. In addition to synchronization, SyncML can be used for device management, although the current implementation in the Series 60 Platform does not support this yet. For more detailed description of the protocol, refer to Chapter 18.
15.2.6
TCP/IP
TCP/IP (transmission control protocol/Internet protocol) is a wellknown protocol suite consisting of several protocols. At the transport layer there are the unreliable UDP and the reliable TCP protocols. UDP is a packet-oriented protocol, which means that the transmission units are packets, whereas TCP is stream-oriented or byte-oriented in which individual bytes may be sent instead of whole packets, for example in the case of retransmissions. At the network layer, there are two protocols: IP, which is responsible for addressing and routing and ICMP (Internet control messages protocol), which is responsible, for example, for checking the status of different routes in the network. Currently IPv4 is supported, but in v7.0 onwards both IPv4 and IPv6 are supported simultaneously. Compared with IPv4, IPv6 has greater address space (128-bit addresses instead of 32-bit addresses) and better support for mobile routing, authentication, and real-time streaming. Between the data link layer and network layer there are two protocols: the address resolution protocol (ARP) and reverse address resolution protocol (RARP) for address resolution from IP addresses to physical addresses, and vice versa. The TCP/IP stack has been implemented into a protocol module, which provides two services. The protocol is not selected explicitly as in IrDA, but only the protocol family is selected to be TCP/IP. After that, if a programmer chooses a reliable socket type, the used protocol is automatically TCP. On the other hand, if an unreliable socket type is chosen, the used protocol is UDP.
15.2.7
Dial-up Networking
Connections from a smartphone to the Internet are established through dial-up networking (or by using the mRouter protocol, mentioned
328
COMMUNICATIONS ARCHITECTURE
above, in Section 15.2.4). This includes the data link layer protocol support for IP protocol and the use of ETel services to establish a physical call to the IAP. In Symbian OS the data link layer connection is provided by the network interface (NIF), such as PPP.nif. The network interface is started by the networks interface manager (NifMan), which is also responsible for monitoring the progress of the connection. The route to the network address is set up by a NIF agent. If there is no route available, the system uses the NifMan to start up an appropriate NIF. NifMan, together with its connection agent, enables the use of dial-up networking via an IAP according to the following phases: A component opens a session with the Socket server and tries to connect to a specic IP address. ESock dynamically loads the TCP/IP protocol family when the socket is opened. IP asks NifMan for a route to the IP address. As there is no connection, NifMan loads its connection agent to set one up. Optionally, the connection agent opens a dialog with which the user may accept connection settings in the Communications database. The connection agent opens a session with the ETel server and asks it to make a call and connect. ETel looks for relevant details for the current port, location, IAP, and modem settings in the Communications database. Note that the Series 60 Platform is used only in smartphones with a built-in GSM modem, so there cannot be external modems. ETel loads the appropriate TSY module (phonetsy.tsy). The TSY module opens a session with C32 (Serial comms server). The TSY tells C32 and Symbian OS kernel to load the correct CSY module and appropriate device drivers. At last, a hardware connection exists. ETel can talk to the phone or modem and tell it to dial up the IAP. On connection, ETel loans the port back to the connection agent, which can now run any scripts necessary to log on to the Internet (password checking). The connection agent hands control back to NifMan, which now activates, for example, the PPP link for any authentication, and to control the remainder of the call.
329
When the PPP asks for a line to be dropped, NifMan returns control to the connection agent, which returns the port to ETel for termination of a call, and the whole stack now unwinds.
PPP
PPP is a simple data link layer protocol enabling access to the Internet through a serial link. Although it is a protocol, it is not accessed through the Socket server, but rather the NifMan uses it for data transfer. The PPP implementation in Symbian OS contains several protocols for providing advanced features of PPP. The link control protocol (LCP) uses echoreply packets to test and ensure link quality. Authentication of the user may be performed with the PPP authentication protocol (PAP), which uses plaintext passwords, or the challenge handshake authentication protocol (CHAP), which uses MD5 and DES (data encryption standard) encryption algorithms. Further information about encryption in communications will be provided at the end of this chapter (Section 15.4.3). PPP supports also several compression methods to improve the link efciency: PPP compression control protocol (CCP), Microsoft PPP compression, PPP predictor compression, and Van Jacobsen header compression.
15.2.8 Bluetooth
Bluetooth is an open data communication standard developed by the Bluetooth special interest group (www.bluetooth.com). It is a low-power, full duplex, digital radio technology with a gross data rate of 1 Mbps. The standard covers both hardware and software layers, as shown in Figure 15.9. The radio uses ISM band (industrial, scientic, and medical) at 2.4 GHz spread-spectrum, fast acknowledgement, frequency hopping, and forward error correction. Spread spectrum spreads the transmission signal into a broad frequency range, which makes it less vulnerable to interference. In addition, there are 79 frequencies at which the signal hops 1600 times per second. This also increases immunity from interference.
RFCOMM LMP L2CAP Audio Bluetooth manager SDP
HCI
Figure 15.9 Bluetooth stack. Note: RFCOMM, see text; CMP, link management protocol; L2CAP logical link control and adaptation protocol; SDP, service discovery protocol; HCI, host controller interface
330
COMMUNICATIONS ARCHITECTURE
Forward error correction means that there is an attempt to correct erroneous received frames without retransmission, by using the redundant bits in the frames. This decreases the need for retransmissions, which again improves the performance. If the link quality is good, there is no reason to use redundant bits for error correction and this function may be turned off. Errors are still detected with fast acknowledgement, which means that received packets are acknowledged immediately in return packets. The acknowledgements do not contain any number information, only either ACK (acknowledgement) or NACK (Negative ACK). If the transmitter receives the NACK, it immediately retransmits the previous packet. The Bluetooth HCI (host controller interface) interfaces with the baseband protocol, which is responsible for data encoding, transmitter management, frequency hopping, security, error detection, and correction and framing. The protocol supports both circuit [synchronous connection-oriented (SCO)] and packet switching [asynchronous connectionless (ACL)]. SCO and ACL channels can be used simultaneously for asynchronous data and synchronous voice transfer. There may be up to three simultaneous SCO channels open. Each voice channel supports a 64 kbps voice link. The asynchronous channel can support an asymmetric link of 712 kbps in either direction, while permitting 57.6 kbps in the return direction. If a symmetric link (i.e. both directions simultaneously, with equal throughput) is used, the maximum transfer speed is 432.6 kbps. The link manager protocol (LMP) establishes, secures, and controls links between devices. It is not used by upper layers, but gives authenticated, established, links to the logical link control and adaptation protocol (L2CAP). L2CAP provides connectionless and connection-oriented data services, protocol multiplexing, and datastream segmentation and reassembly. The service discovery protocol (SDP) allows Bluetooth devices to discover, search, and browse services. It is a distributed protocol implemented on top of L2CAP. RFCOMM is not a core Bluetooth layer, but allows an interface between existing services and the Bluetooth stack. RFCOMM emulates the RS-232 protocol and, for example, to IrOBEX it presents an interface fully similar to RS-232. The Bluetooth device may register services, which it provides to other devices, in the Bluetooth Security Manager and SDP database. The Bluetooth Security Manager enables services to set appropriate security requirements that incoming connections to that service must meet. Security settings dene simply whether authentication, authorization, or encryption is required or not. The SDP database contains the attributes of the service. One attribute may specify, for example, the port number in which the service is available. If a device knows
331
that a service is available in a specic port in the remote device and no authentication or encryption is required, it may start using the service directly.
15.2.9
GPRS
GPRS (General Packet Radio Service) is a radio-based wide-area packet data service extending the CSD service of the GSM network. Compared with CSD, data transfer is packet-switched rather than circuit-switched. Packet switching suits well the transfer of IP packets, for example. Billing can be based on the number of transferred packets, not on connection time. However, operators may choose whatever billing method they wish. There is no need to maintain the connection between the terminal and the network if packets are not transferred. This enables several users to share the same radio interface channels, which in turn improves the utilization of the network. Channel allocation is very exible in GPRS. In principle, it is possible to allocate 18 time slots for each user independently in the down and up link. However, the number of supported time slots depends on the capabilities of the terminal. In theory, with use of the maximum number of time slots and lightest coding scheme it is possible to achieve a transfer rate of 171 kbps. There are four coding schemes, which differ from each other with respect to the sensibility to transfer errors. If the link quality is low, a heavier coding scheme is used, which reduces the transfer rate (Cai and Goodman, 1997). There are three types of GPRS terminals: class A, class B, and class C. Classes differ from each other in terms of complexity and the support of simultaneous circuit-switched and packet-switched connections. Class A terminals allow the use of simultaneous circuit-switched and packet-switched calls. It is possible, for example, to browse web pages at the same time a speech call is active. A class B terminal allows the creation of both circuit-switched and packet-switched connections, but they cannot be active simultaneously. Class C terminals do not allow the establishment of circuit-switched and packet-switched connections simultaneously. There may be class C terminals, that do not support circuit-switched connections at all. For UMTS (Universal Mobile Telecommunications System), there are three other GPRS terminal types. The interested reader should read GSM specication 02.60 for further information. In Symbian OS, applications may choose GPRS as one bearer of application data, but it does not provide any programming interface.
15.2.10 HTTP
HTTP (hypertext transfer protocol) is a simple text-based protocol for content transfer on the Internet. It was originally a stateless protocol,
332
COMMUNICATIONS ARCHITECTURE
where only one requestresponse pair was served per connection; in contrast, HTTP1.1 supports leaving the connection open after transmission and using it for sending further data. Basic client server communication over TCP/IP is possible, but there are often intermediaries, such as proxies and gateways, between the browser and server. A proxy is a forwarding agent, that rewrites all or part of the request before forwarding it to the server. A gateway receives requests and translates them to the underlying servers. In addition to proxies and gateways, there are tunnels, which are relay points between two endpoints. By using a tunnel, a message can be passed unchanged, for example, across the rewall. There is no open programming API available for application developers in the Series 60 Platform yet. HTTP1.1 is the only supported technology for the transfer of midlets, because it is the only protocol required by the current MIDP (mobile information device prole) specication. More information about MIDP and HTTP1.1 is provided in Chapter 20.
15.2.11
WAP
WAP (wireless application protocol) is a protocol stack for content browsing on low-bandwidth, high-latency networks. It is suitable for many applications and it is used for delivering MMS messages. The protocols of the WAP stack are shown in Figure 15.10. WAP is bearerindependent. Any network capable of conveying WAP datagrams may be used. WDP (wireless datagram protocol) provides network and transport layer functions, such as port level addressing, datagram segmentation and reassembly, selective retransmission, and error recovery.
Wireless a e (WAE) Wireless session protocol (WSP) Wireless transaction protocol (WTP) Wireless transport layer (WTL) Wireless datagram protocol (WDP) Bearers:GSM, GPRS, etc.
Figure 15.10 WAP (wireless application protocol) stack. Note: GSM, global system for mobile; GPRS, General Pachet Radio System
333
WTP (wireless transaction protocol) supports connectionless and connection-oriented transactions. It also handles the retransmission of datagrams. WTLS (wireless transport layer security) provides data encryption between client and server. It can also ensure data integrity and can detect whether data have been repeated. WSP (wireless session protocol) emulates HTTP (is modeled after HTTP) in a restricted way. Using connectionless service, the WSP communicates directly to WDP without WTP. Connection-oriented service takes place through WTP. This type of service enables capability negotiations and header caching.
334
COMMUNICATIONS ARCHITECTURE
COM. Second, the numbering starts from 0 in the emulator, but from 1 in the PC. Thus, the emulator port COMM::0 is mapped to PC port COM1, and so on. IR ports can be used in a PC which does not have the ports by attaching a mobile phone, for example, to the PC. This allows the use of the IR port of the mobile phone. When the emulator is started, it looks for IR devices and will use one if found. For Bluetooth, the emulator looks for Nokias Bluetooth device (i.e. Nokia Connectivity Card DTL-4; go to www.forum.nokia.com). If one is found, it is possible to send and receive Bluetooth packets. The kit has to be connected to the computer via both the USB (universal serial bus) and the serial cables, because it draws power from USB, but the emulator supports only the serial cable for data transfer. Note that for a Quartz 6.1 emulator one must use Ericssons Bluetooth Application Tool Kit (www.tality.com). A GSM phone may be connected through an IR port to the emulator. In addition, network connections can be established by using a null modem cable.
15.3.1
Condentiality
Local communications, such as RS-232, infrared, or Bluetooth are difcult to snoop on without getting caught. The eavesdropper needs proper receivers and must be in the intermediate space between communicating parties. Global or wide-area communications, such as the Internet or GSM, are more easily snooped with proper devices. To gain access to application-level information, protocol headers and other framing information may be extracted with a protocol analyzer tool. The protocol analyzer knows the encoding and decoding functions (and protocol message structure) of each protocol in the suite and may be used to nd the relevant information from a large amount of redundant protocol control information. If this extracted information contains, for example, passwords in plain text, the eavesdropper has free heir to utilize the users account in any way.
PROTECTION MECHANISMS
335
15.3.2
Integrity
Condentiality does not imply data integrity. In fact, data may be highly integrity critical but still not require any condentiality. Public keys are good examples of such data. Although it is quite easy to protect against eavesdropping by encrypting the transmitted data, it is impossible to prevent any modications, either sensible or absurd. Cryptography provides a means of detecting if integrity of the data is lost, but there are no means to guarantee that no modications are made. One common type of attack against integrity is forgery of critical data. E-mail messages are easily forged by using directly the SMTP protocol to upload forged messages to the mail server. Also, IP addresses may be forged. If we trust some party and download software from a forged IP address, we may, in the worst case, cause a lot of damage to the existing software.
15.3.3 Availability
Availability ensures that any server or service is always available. Attacks against the availability aim at authentication, protocol, or service. By getting the right password, the eavesdropper may do anything with the credentials of the owner of the password. Attacks on the service and protocol try to run the service into a state in which it accepts anything, even commands from the snooper. The attacher attempts to create such a State by causing exceptions in the attacked software. If exceptions are not handled properly, the server may enter an undened state, accepting any input from the attacker. One common way is to use buffer overow. If there is no checking of boundaries of the buffer in software, external users may write data into areas not intended for users, which may break down the state of the server. The attacker may close down the server or read condential data from it.
15.4
Protection Mechanisms
Very little can be done to prevent the physical snooping on a communications medium, especially if data are transferred through several networks around the world. Encryption ensures the condentiality of data with a high probability, although there is no encryption algorithm that cannot be broken given enough computing and memory resources. Although encryption makes it more difcult to read the data, it does not prevent any modications to the data. To ensure integrity in addition to condentiality, a message certicate, such as
336
COMMUNICATIONS ARCHITECTURE
a digital signature, may be used. This reveals whether the message has been modied, but it cannot prevent the modication in any way. Availability may be ensured by authentication and by preventing the distribution of the authentication information, such as passwords, to nontrusted persons.
PROTECTION MECHANISMS
337
Original IP packet
IP
TCP header
Data
Transport mode
IP
TCP header
Data
Tunnel mode
IP
IP
TCP header
Data
Figure 15.11 IPSec in transport and tunnel mode. Note: IP, Internet protocol; TCP, transmission control protocol
The IPSec architecture allows a user to specify his or her own security policy for different trafc ows. Some ows may require light security whereas others may require completely different security levels. For example, the security policy may determine that in the network gateway all trafc between local and remote subnets be encrypted with DES and authenticated with MD5. In addition, all Telnet trafc to a mail server from the remote subnet require encryption with Triple-DES (3 DES) and authentication with SHA-1. These algorithms will be described in more detail later in Section 15.4.3.
15.4.2
Authentication
Authentication may be based on information, biometrics, or physical properties. The security is lost if someone can snoop the information or forge or steal the property. When the piece of information is used in an open network, it should be encrypted each time of use. Some protocols for downloading mail (POP3 and IMAP4) use authentication, but they do not encrypt the passwords, making it easy to snoop the passwords and read others mail messages. In PPP, which also uses authentication with plain text passwords, the risk of revealing the password is small, because a point-to-point connection to an IAP is used. In addition to a password, a biometric property, such as blood vessel organization in the retina, or a ngerprint, may be used. The third option is to use some physical, owned property, such as a SIM (subscriber identity module) card, for authentication. Because physical properties may be stolen, some application in which money transactions are transferred over a Bluetooth from a smartphone to a cashier server should not rely only on this means of authentication. Thus, the future smartphones should have a built-in ngerprint identication device to authenticate the user in a sufciently reliable way.
338
COMMUNICATIONS ARCHITECTURE
RSA
The rst public key algorithm was invented by Whiteld Dife and Martin Hellman; the most popular algorithm is RSA, named after its inventors Ron Rivest, Adi Shamir, and Leonard Adleman. The security of the RSA algorithm is based on the difculty in factoring the product of two very large prime numbers. A drawback of the algorithm is that it is quite slow and can operate only on data up to the size of the modulus of its key. Fortunately, several blocks up to the size of the modulus of the key can be encrypted in sequence. A 1024-bit RSA public key can only decrypt data that is less than or equal to that size. Actually, the size is little bit smaller (1013 bits), because the encoding requires 11 additional bits. The RSA method is the de facto standard for key exchange and digital signatures.
PROTECTION MECHANISMS
339
Software Certicates
Although encryption ensures the condentiality of data, it cannot guarantee integrity. A digital signature uses one-way hash functions to reduce a document down to a digest, which is then encrypted by using the private key and, for example, the RSA algorithm. The digest is appended to an original document. Verication of the signature entails
340
COMMUNICATIONS ARCHITECTURE
running the original document through the identical hash function to produce a new digest value, which is compared with the decrypted value in the received document. If these digests do not match, the document has lost its integrity. In the same way, it is possible to use digests as software certicates to ensure that the integrity of downloadable software has not been lost. In Symbian OS there is a PC command line tool The Certication Generator that creates a privatepublic key pair and issues certicate requests. The resultant private key is used digitally to sign installation les, enabling the install system to authenticate them. The secure installation process rst checks the signature on the installation le by using the public key in the developers certicate to ensure that the install package is signed by the developers private key. It then checks the signature on the developers certicate by using the organizations public key from the organizations certicate to ensure that the key pair really does belong to the person named on the certicate.
SUMMARY
341
15.6
Summary
In this chapter we have described the communications architecture of Symbian OS. The architecture enables dynamic extension of communications features, without rebooting the device, with the help of loadable plug-in modules. The architecture enables dynamic extension of communications features via plug-in modules without rebooting the device. These modules are used by communications servers in the realization of different communications technologies and protocols. There are four communication-related servers in Symbian OS and the Series 60 Platform: the Serial communications server, the Socket server, the Telephony server, and the Message server, each providing an own client-side API through which the services, provided by communications modules, are accessed. There are several techniques supported by Symbian OS for data transfer, content browsing, and messaging. Data may be transferred locally through RS-232, infrared, or Bluetooth or globally by using TCP/IP, GSM, or GPRS. Both Web and WAP browsing are supported, and messages may be sent as e-mail, short messages, multimedia messages, or fax. There are three kinds of threats to communications security: condentiality, integrity, and availability. Condentiality may be ensured to a great extent by encryption algorithms. Although integrity cannot in general be ensured, it is still possible to detect when the integrity of data is lost. The main method for implementing this is to use digital signatures with the help of asymmetric ciphers. Availability can be divided into two issues: availability for intended users by an access mechanism based on authentication, and denial of service, where the service is blocked from intended users where there is an enormous number of forged service requests. A user may be authenticated based on information, biometrics, or physical properties, but there are no general protection mechanisms against denial-of-service attacks.
16
Communications Application Programming Interface
As described in the previous chapter, use of any communications service is based on one of the communications servers: the Serial communications server, the Socket server, the Telephony server, and the Message server. Each server has a client-side application programming interface (API), through which the communications server and the underlying plug-in communication module are accessed. Thus, the service API provided to the client is similar regardless of the specic communications module. The use of each communications server is similar. The client-side API always includes a class that provides a handle to the server. The handle is used to create a session between the client and server processes. The actual communication takes place in subsessions provided by one or more classes derived from the RSubsessionBase class. This chapter contains a description of how to use different communications APIs in the Series 60 Platform. As a concrete example, the development of a generic data-transfer engine is shown. The engine is an active object derived from the CActive class. In addition to the engine itself, there are usually two other active objects used: one for transmitting data and one for receiving data. The engine is an active object because it takes care of the connection establishment, which is an asynchronous service. Three classes instantiated from CActive are needed, because one active object may issue only one request at a time so that a read request in the receiving object does not block the send request in the transmitting object. The communications engine of the rockpaperscissors (RPS) game implements the virtual functions of the MCommsBaseClass interface, presented in Section 15.1.4, to ensure it conforms to the generic communications pattern.
343
16.1
Communications Infrastructure
In addition to client-side APIs of communications services, there are a few other concepts that are frequently used by the developer and user of communications software. The communications database is a record of common communications settings used by several communications services. It was described in Section 15.1.3. NifMan (network interface manager) is responsible for monitoring network connections and is required to start up an appropriate network interface (NIF) established by network agents. The interface provides a connection established by the Telephony server (ETel), through which a route is created to a destination station or network. NifMan is described in detail in the section on the socket server (Section 16.3).
16.2
344
opening: the port is opened and for instance, the access mode to the port is determined: exclusive, shared, or pre-emptive; conguration: serial communications have a rich set of communications parameters, with the use of start and stop bits, number of data bits, use of parity bit based error detection, baud rate, and handshaking options; data transfer: reading and writing of a serial port, takes place; Closing: the session and subsessions are closed to release the port for other applications, if opened in the exclusive mode. The declaration of the serial communications engine class is as follows:
class CSerialEngine : public CActive, public MCommsBaseClass { public: enum TCommType // These may be used to choose the type of { // communication ERS232, EIRComm }; static CSerialEngine* NewL(void); ~CSerialEngine(); public: // New functions private: // From MCommsBaseClass void Initialize(); void OpenL(); void ConfigureL(); void Transmit( TDesC& aTransmittedData ); void Receive(); void Close(); private: // From CActive void RunL(); void DoCancel(); private: CSerialEngine(); void ConstructL(void); private: // Data RCommServ iServer; RComm iCommPort; TCommType iCommPortType; CTxAO *iTransmittingActiveObject; CRxAO *iReceivingActiveObject; };
TCommType may be used to identify the type of communications: RS-232 or infrared. It results in only a few changes to the source code. The CSerialEngine class is designed to take care of connection establishment. Thus, RunL() is called by the active scheduler when the connection is ready. However, there is no connection in serial communication and so the implementation of RunL() is empty. It may be implemented, for example, in the sockets engine. CSerialEngine
345
creates the active objects, taking care of data transfer. Note that the engine also has handles to services providers as members. This is a common way to implement any active object. The rst phase (initialization) in the communications pattern is quite straightforward to implement. Static functions LoadPhysicalDevice() and LoadLogicalDevice() from the User class are used to load the physical and logical device drivers, respectively. In WINS builds, the le server must be started before the device drivers can be loaded. It is a common error not to ignore the KErrAlreadyExists value when loading the drivers. This value should not cause a leave but should be handled in the same way as the KErrNone value. The names of physical device drivers are different for WINS and MARM builds. The driver is ecdrv.pdd in WINS builds and is euart1.pdd in MARM builds. In both builds, the same logical device driver (ecomm.ldd) is used. Device drivers can be dened as literal constants in the header le. It is then easy to change the device driver names:
// Device driver names _LIT(KLddName,"ECOMM"); #if defined (__WINS__) _LIT(KPddName,"ECDRV"); #else _LIT(KPddName,"EUART1"); #endif // Communication modules _LIT(KRS232,"ECUART"); _LIT(KIRCOMM, "IRCOMM");
When both device drivers are in place, the Serial communications server may be started. This requires only one function call: StartC32(). The name of the CSY module depends on whether RS-232-based or infrared-based communications are required. In the RS-232 case, ecuart.csy is used, whereas infrared communications require the ircomm.csy module. It is not necessary to load the communication module in Bluetooth. The only thing needed to be done with respect to serial communications is to load the appropriate device drivers. Other initialization procedures will be performed by the Bluetooth protocol module. The InitializeL() function of the serial communication will look like the following piece of code:
void CSerialEngine::InitializeL() { TInt err;
346
#if defined (__WINS__) // Required in WINS to enable loading of RFs fileServer; // device drivers User::LeaveIfError( fileServer.Connect() ); fileServer.Close(); #endif // Load device drivers err=User::LoadPhysicalDevice( KPddName ); if ( err != KErrNone && err != KErrAlreadyExists ) User::Leave( err ); err = User::LoadLogicalDevice( KLddName ); if ( err != KErrNone && err != KErrAlreadyExists ) User::Leave( err ); // Start the server and create a session StartC32(); User::LeaveIfError( iServer.Connect() ); // Ask the server to load the CSY module if ( iCommPortType == ERS232 ) User::LeaveIfError( iServer.LoadCommModule(KRS232) ); else User::LeaveIfError( iServer.LoadCommModule(KIrComm)); // Create receiving and transmitting active objects // using normal two-phase construction. // Code omitted. }
There are several functions in the RComm class that may be used to open the port. The arguments of the functions contain the session handle, the port to be opened, the access mode, and, optionally, the role. The access mode may be exclusive, shared, or preemptive. The exclusive mode prevents the use of the port from other processes. The processes may share the port if both open the port in the shared mode. The preemptive mode allows another client to open the port in the two other modes. Note that when using ircomm.csy, only the exclusive mode should be used. The role denes whether the port is opened in the data terminal equipment (DTE) or the data circuit terminating equipment (DCE) role. DCE is usually a device, such as a modem, used by the DTE for data transfer. In the DCE mode, the smartphones serial port is congured as a port of a modem. The serial ports are numbered from zero, so the port corresponding to the COM1 port in Windows is port COMM::0 in Symbian OS. Another thing affecting the port name is the type of serial technology used. RS-232 ports are named COMM::0, but infrared ports IRCOMM::0. The port name is the only difference in addition to the CSY module, which is different in infrared communication compared with communication based on RS-232:
347
Serial communications have several conguration parameters. Before changing the conguration it is advisable to save the existing conguration, because the port may be shared with another process. The existing conguration may be read with the Config() function. It may also be used in the initialization of a TCommConfig structure, which makes it unnecessary explicitly to set every member of the structure. It is good programming practice to check whether the required conguration is supported by the port before changing it. This is done with the TCommCaps structure, which is used in a way similar to the TCommConfig structure, by calling the Caps() function:
void CSerialEngine::ConfigureL() { TCommCaps currentCaps; iCommPort.Caps( currentCaps ); TCommConfig portConfiguration; iCommPort.Config( portConfiguration ); // Check port capabilities if ( (currentCaps().iRate & KCapsBps57600) == 0 ) User::Leave( KErrNotSupported ); // Change the configuration portConfiguration().iRate = EBps57600; User::LeaveIfError( iCommPort.SetConfig (portConfiguration) ); }
Before conguration, all pending transmitting and receiving requests should be cancelled; otherwise a panic will result. Requests are cancelled simply by calling the Cancel() function of the RComm class. The RComm class provides several functions for transmitting (Write()) and receiving (Read()) data. Before any data transmission the serial communications chip must be powered up. This is done with the Read() function, in which the data length argument is zero. The Serial server always handles 8-bit data, even in the Unicode system, which may require that the data be cast into the correct type before transmission and after receiving. What happens when data is received by the engine? When reading, the receiving active object issues a read request with an empty buffer. Application continues with its other duties and the Serial server monitors the incoming data. When the data are received, the server lls
348
the buffer, and the receiving active object signals the application. The engine may then read the data from the buffer. Active objects can have only a single request active at any time, so wrapping read and write into the same class would mean that these requests cannot be active at the same time. Either two objects of the same class or instances of two different classes are needed. The latter approach is the method used in our examples:
void CSerialEngine::Receive() { if ( !iReceivingActiveObject->IsActive() ) { // There is another function to read the received // data from a member variable iReceivingActiveObject->Recv(); } } void CSerialEngine::Transmit( TDesC& aTransmittedData ) { if (!iTransmittingActiveObject->IsActive()) { iTransmittingActiveObject->Send( aTransmittedData ); } }
The following two functions issue the read and write requests. The received data are read into an 8-bit buffer, from which it is read and cast to Unicode, if necessary, by the functions of the CSerialEngine class. There are several Read() functions to be used in the RComm class. If we do not know the amount of received data beforehand, the version used in the next example is very useful. It returns after a time interval without waiting for the whole buffer in the descriptor to be lled. When a timeout occurs, the received data buffer may be empty, although data have been received. It depends on the serial protocol module implementation whether the data are stored in the buffer or must be read using, for example, ReadOneOrMore(). The following example assumes that iDataBuf contains any received data after the timeout:
void CRxAO::Recv() { // Change from ASCII to Unicode in RunL() method // Data should be read by the CSerialEngine object // using a separate function iCommPort.Read( iStatus, KMaxTimeInterval, iDataBuf ); SetActive(); } void CTxAO::Send( TDesC& aData ) {
SOCKET SERVER if (!IsActive()) { TPtrC8 outputBufPtr.Copy(aData); iDataBuf = outputBufPtr; iCommPort->Write(iStatus, iDataBuf); SetActive(); } }
349
Finally, the port is closed. It is not necessary to cancel the requests before closing the port because the Cancel() function is called automatically. The session is closed in a similar way:
void CSerialEngine::Close() { iCommPort.Close(): iServer.Close(); }
In addition to the session to the Serial communications server, the RCommServ class provides information about the number of CSY modules loaded by calling the NumPorts() function. The GetPortInfo() function is used to obtain a TSerialInfo class of a named port. TSerialInfo contains information about the name of the port and the lowest and highest unit numbers.
16.3
Socket Server
The Socket server is used according to the same principles as the Serial communications server. What is different from serial communications is that there are typically several subsessions instead of one. There may be several sockets open for data transfer between applications. In addition, some sockets may be used for special services such as host-name resolution or device discovery in case of IrDA (infrared data association) and Bluetooth sockets. The six protocol stacks implemented in the Series 60 Platform are TCP/IP (transmission code protocol/Internet protocol), IrDA, Bluetooth, short message service (SMS), Psion Tink protocol (PLP), and wireless application protocol (WAP). Although there is the PLP protocol module, it has been replaced by mRouter (see Section 15.2.4), which should be used. In addition, SMS should be used through the messaging and not the protocol interface, as will be shown in the next chapter. The client-side API of the Socket server is provided by two classes: RSocketServ, which provides a handle to the server, and RSocket,
350
which implements the communications socket. Both classes are dened in es sock.h. In addition to the RSocket class, RHostResolver may be used for the host-name and device-name resolution services, and RServiceResolver may be used for service-lookup facilities. RNetDatabase is the fourth class that may be used for accessing a network database. Note that the network database is not the communications database. The latter is used for storing general settings of the connections, whereas the network database contains protocol-specic information, such as service identiers (IDs) stored into the IrDA information access service (IAS). The RSocketServ class provides the same kind of services to the Socket server as the RCommServ provides to the Serial server. The NumProtocols() function may be used for getting the number of protocol modules known by the Socket server, in the same way that NumPorts() returns the number of CSY modules in the case of serial communications. GetProtocolInfo() returns information on all protocols, as GetPortInfo() returns information about a serial port. Another way to get information about the protocol is to use the FindProtocol() function. It returns similar information to that provided by GetProtocolInfo() about a named protocol.
SOCKET SERVER
351
16.3.3
NifMan
The network interface manager, NifMan, is responsible for route setup for sockets protocols. In addition, it selects the correct network interface for the route. NifMan provides progress information on connection establishment through the RNif class, which provides both asynchronous ProgressNotification() and synchronous Progress() functions for getting the current state of a dial-up connection.
352
phase. One argument, the number of message slots, can be passed to the function. The number indicates the number of asynchronous operations that are allowed to be in progress at any time. The default value is KESockDefaultMessageSlots, which is 8. Too small a value may result in the KErrServerBusy return value. The suitable value for message slots is N + 2, where N is the number of asynchronous services that the client may request (connection establishment, data receive, data transmit, etc.). There should always be one slot available to cancel the service request. If the client exits but it cannot cancel the requests, it panics. The last slot is reserved for a synchronous service request. One is enough, because there can be only one synchronous request active at one time. An initialization function creating a session to the socket server is as follows:
void CTcpIpSocketServerEngine::InitializeL() { User::LeaveIfError( iServerSocket.Connect() ); }
After initialization, a socket is opened. A socket may be opened in two ways: either as a blank socket, or as a socket associated with a specied protocol. Blank sockets cannot be used for data transfer until they have been paired with a client by the Accept() method. When opening a socket, its type and role must be decided. The role is either a server or a client. In the server role, two sockets must be opened. One for listening to incoming connection requests and one blank socket for data transfer to the client after the acceptance of the connection request:
void CTcpIpSocketServerEngine::OpenL() { TInt result; if ( iSocketRole == EClient ) { result = iSocket.Open( iServerSocket, KAfInet, KSockStream, KUndefinedProtocol); User::LeaveIfError( result ); } else { result = iListernerSocket.Open( iServerSocket, KAfInet, KSockStream, KUndefinedProtocol ); User::LeaveIfError( result ); result = iSocket.Open( iServerSocket ); User::LeaveIfError( result ); } }
SOCKET SERVER
353
Conguration depends on the socket type and its role. A connectionless socket is easy to congure. A local address is simply assigned to it, using the Bind() function. Clients of the socket stream type must assign the address of the remote socket so that the sockets remain together during the connection. This is done by using the Connect() method. In the server side of streaming sockets, the listener socket listens to incoming connection requests and the other socket serves them:
void CTcpIpSocketServerEngine::ConfigureL() { if ( iSocketRole == EClient ) { TInetAddr serverAddr( INET_ADDR(127,0,0,1), KServerPort ); iSocket.Connect( serverAddr, iStatus ); } else { TInetAddr anyAddrOnServerPort( KInetAddrAny, KServerPort ); iListenerSocket.Bind( anyAddrOnServerPort ); // Set up a queue for incoming connections iListenerSocket.Listen( KQueueSize ); // Accept incoming connections iListenerSocket.Accept( iSocket, iStatus ); } SetActive(); }
There are different functions for reading and writing data, depending on the socket type and role. For datagram sockets SendTo() and RecvFrom() are used. For stream sockets, several versions of Send() and Recv() may be used. All functions take a buffer to be sent or into which the received data are stored, as an argument. Note that, as in the case of serial communications, data are always transferred in 8-bit bytes, even on a Unicode system. An optional parameter may be used to set the transmission ags, such as urgent data. Another optional argument is the length, which indicates the actual data received or sent. The write object should in most cases use a timer to avoid innite waiting in case the write cannot be done:
void CTcpIpSocketServerEngine::Receive() { if ( !iSocketRxAO->IsActive() ) { iSocketRxAO->Recv(); } } void CRecSocketAO::Recv() { if (!IsActive())
354
After use, the socket is closed by calling Close(). Before closing, all pending asynchronous operations should be cancelled with CancelAll(). This function call cancels all operations (read, write, inputoutput control, connect, and accept), except shutdown, which cannot be cancelled. Although Close() is a synchronous function, it calls the asynchronous Shutdown() function, which closes the socket in the normal way (i.e. completes) after both socket input and output have been stopped.
LIBC
Because of the large amount of communications software written in pure C, there is also a C language implementation of the BSD 4.3 sockets in Symbian OS called LIBC. This helps the porting of communications software, because it enables the use of communications engines implemented in C language. The LIBC library contains a standard TCP/IP library including the address resolution protocol (ARP), reverse address resolution protocol (RARP), Internet protocol (IP), Internet control messages protocol (ICMP), transmission control protocol (TCP), and user datagram protocol (UDP).
Host Resolution
In addition to data transfer, sockets may be used for other services, such as host-name resolution and device discovery. The RHostResolver class provides host-resolution services. It is used in exactly the same way as the objects of the type RSocket. The host resolution is applied in four services: To obtain names from addresses or vice versa, or to get and set local host names. The actual service is protocol-dependent. For TCP/IP sockets the host resolution accesses the domain name service (DNS) to convert between textual and numeric IP addresses. For IrDA, the host resolution resolves all devices in the neighborhood of the requesting devices. Examples will be provided in the following sections.
SOCKET SERVER
355
through a client-side API: IrMUX, which provides unreliable service, and IrTinyTP, which provides reliable data-transfer service. RHostResolver is used for device discovery rather than for name resolution, but otherwise IrDA sockets are used in the same way as TCP/IP sockets. IAS (information access service) is a database for saving information about IrDA connections and their properties. The IAS database may be accessed after a successful device discovery. The database may be queried, for example, for remote port numbers of IrTinyTP, IrCOMM, or IrOBEX services (see Glossary) so that several services may share the same link by using different port numbers. The client-side API of the IrDA sockets has ve concepts: IrTinyTP socket protocol for reliable transport, used through RSocket handle; IrMUX socket protocol for unreliable transport, used through RSocket; IrDA discovery for host resolution, used through RHostResolver; IAS database queries, used through RNetDatabase; IAS database registration, used through RNetDatabase. The initialization and opening phases of IrDA sockets are similar to those of TCP/IP sockets. However, conguration is different, because an IrDA device must discover another device with which to communicate. Device discovery is implemented through the name resolution interface by using an instance of the RHostResolver class and its GetName() function. The server does not perform device discovery, rather, it must be discovered:
void CIRSocketEngine::ConfigureL() { TInt result; TPckgBuf<TUint> buf(1); // IrLAP does the device discovery, when device discovery // socket option is set sock.SetOpt( KDiscoverySlotsOpt,KLevelIrlap,buf ); result = iHostResolver.GetByName( KHostname,iHostEnt ); resolver.Close(); User::LeaveIfError( result ); addr = TIrdaSockAddr( iHostEnt().iAddr ); }
356
COMMUNICATIONS APPLICATION PROGRAMMING INTERFACE { TInt result; RNetDatabase rnd; TIASQuery query; TIASResponse response; result = rnd.Open( iSocksvr, iProtocolInfo.iAddrFamily, iProtocolInfo.iProtocol ); User::LeaveIfError( result ); query.Set( aClassName, aAttributeName, addr.GetRemoteDevAddr() ); rnd.Query( query, response, status ); User::WaitForRequest( status ); // Freezes the thread return response; }
The class names and their attributes are given in Table 16.1. The TIASResponse return value may have four types, from 0 to 3. Type 0 results are missing results (i.e. results are not given owing to errors), type 1 results are integers; type 2 results are a sequence of bytes; and type 3 results are strings.
Table 16.1 Information access service (IAS) class and attribute names; for more details, see the Glossary Class name Device IrDA:IrCOMM Attribute name Device name IrLMPSupport Parameters IrDA:IrLMP:LsapSel IrDA:TinyTP:LsapSel IrDA:InstanceName IrDA:TinyTP:LsapSel Response Remote device hostname Level of support by remote device for IrMUX Collection of parameters detailing IrCOMM support Range of remote port numbers for IrCOMM service Range of remote port numbers for TinyTP service Name of IAS instances on remote device Range of remote port numbers for IrOBEX service
IrDA:IrOBEX
16.3.6
Bluetooth Sockets
Bluetooth sockets are based on a Bluetooth host controller interface (HCI), which species a command interface to a Bluetooth device. There are two client APIs: a socket API for new applications, and a serial API for legacy applications (Nokia, 2001a). Through the client-side API of the Socket server, it is possible to access L2CAP (logical link control and adaptation protocol) and the RFCOMM protocol (see the Glossary) as well as the service discover protocol (SDP) and Bluetooth Security Managers, as shown in Figure 16.1. The Bluetooth manager is executed in its own thread, created by the Bluetooth protocol module. It interacts with the user through the conguration manager. Three distinct service security levels are dened: high, for services that require authorization and authentication (automatic access is granted to trusted devices only);
SOCKET SERVER
357
Application Serial comms server API Serial port emulation over RFCOMM
Host controller interface (HCI) API for clients that need access to raw HCI HCI Bluetooth hardware driven through the ecomm.ldd device driver
Figure 16.1
medium, for services that require authentication only; and low, for services open to all devices. Before providing any service, it must be registered with both the Bluetooth security manager (if security is required) and the service database. In the same way, the use of any service requires not only device discovery but also service discovery. If no special service parameters are required (a client already knows in which port the service is available) a data connection may be established between devices without service discovery. The pattern of using Bluetooth services depends on the role of the communicating software module. It may be a client or a server. In each case the initialization starts as in the case of the Serial communications server. Thus, rst, the required device drivers and communications modules are loaded. Before a connection can be established, a client: nds a device, by inquiry or registry lookup; raises a SDP query for services and their attributes; if the client already knows the port of a specic service, it is not necessary to execute service discovery. After device and service discovery, the client creates a connection to the Bluetooth server host. On the server side, the service might have been registered to the SDP and Bluetooth security manager databases. Thus, in the server, the service initialization may require:
358
local channel allocation for the service, service registration in the SDP (e.g. reserved channel stored), security registration in the Bluetooth security manager. After the connection has been established, the generic data-transfer and connection-closing phases are executed both in the client and server side. The following header le gives the server-side functions:
// INCLUDES #include <e32base.h> #include <btmanclient.h> #include <bt_sock.h> #include <btextnotifiers.h> // CONSTANTS const TInt KRPSServiceId = 0x5021; //##ModelId=3C67AF470095 class CBTServer : public CActive { public: // // Constructors and destructor static CBTServer* NewL(); // Static constructor static CBTServer* NewLC(); // Static constructor virtual ~CBTServer(); // Destructor (virtual) protected: CBTServer();
// Default constructor, protected to // allow derivation void ConstructL(); // Second phase construct
public: // Methods derived from CActive void RunL(); void DoCancel(); public: // New methods void CheckBluetoothL(); void CheckedBluetoothL(); void LoadDriversL(); void ReserveLocalChannelL(); void RegisterBTMan(); void UnregisterBTMan(); void RegisteredBTManL(); void ConnectSdpL(); void ConnectSocketServerL(); void WaitForConnectionL();
SOCKET SERVER void CloseRemoteL(); void ReadSizeL(); void ReadDataL(); void ProcessDataL(); CArrayFix<TInt16>* ReadTableL( TPtrC8& aData ); TInt16 ReadShortL( TPtrC8& aData ); protected: // Data enum { EStateNotConnected, EStateCheckingBluetooth, EStateRegisteringSecurity, EStateAcceptingConnections, EStateReadingSize, EStateReadingData }; TInt iStateMachine; CCxContextBoard* iBoard; TUint8 iLocalChannel; RSocketServ iSocketServ; RSocket iListenSocket; RSocket iRemoteSocket; RBTMan iBTMan; RBTSecuritySettings iSecurity; RSdp iSdp; RSdpDatabase iSdpDb; TSdpServRecordHandle iSdpHandle; RNotifier iNotifier; TPckgBuf<TBool> iNotifierResult; HBufC8* iData; TPtr8 iDataPtr; };
359
The client has functions for device and service discovery. Most of the other functions are used for browsing the service attributes when the service record has been received from the remote device; we will explain these functions in detail later. The following is a declaration of the client class:
#include <e32base.h> #include <e32std.h>
360
class CSdpAgent; class CBTClientEngine : public CActive, public MSdpAgentNotifier, public MSdpAttributeValueVisitor { public: IMPORT_C static CBTClientEngine* NewL(); ~CBTClientEngine(); protected: CBTClientEngine(); void ConstructL(); public: // from CActive void RunL(); void DoCancel(); public: // from MSdpAttributeValueVisitor void VisitAttributeValueL( CSdpAttrValue &aValue, TSdpElementType aType); void StartListL(CSdpAttrValueList &aList); void EndListL(); protected: // from MSdpAttributeValueVisitor void NextRecordRequestCompleteL(TInt aError, TSdpServRecordHandle aHandle, TInt aTotalRecordsCount); void AttributeRequestResult( TSdpServRecordHandle aHandle, TSdpAttributeID aAttrID, CSdpAttrValue* aAttrValue); void AttributeRequestComplete( TSdpServRecordHandle aHandle, TInt aError); protected: void DiscoverRemoteL(); void DiscoveredRemoteL(); void QueryRemoteL(); void QueriedRemote(); void ConnectRemoteL(); void CloseRemoteL(); void WaitForDataL(); void WriteDataL(); private: enum TState {
SOCKET SERVER EStateNotConnected, EStateDiscovering, EStateQuerying, EStateQueried, EStateConnecting }; RFs iFs; RNotifier iNotifier; TBTDeviceResponseParamsPckg iDiscoveryResponse; TBTSockAddr iRemoteAddr; RSocketServ iSocketServ; RSocket iSocket; RTimer iTimer; CSdpAgent* iSdpAgent; TInt iStateMachine; TInt iRemoteChannel; TUUID iPreviousUUID; };
361
Bluetooth Server
The server component creates a session to the Bluetooth security manager and SDP database servers to register the service. A session to the Socket server is required to enable the use of the Bluetooth protocol module. Note that the server is an active object, that uses asynchronous service requests to the server. The rst function to be called is CheckBluetoothL(), which is used to check that the Bluetooth module is powered on:
void CBTServer::ConstructL() { User::LeaveIfError( iBTMan.Connect() ); User::LeaveIfError( iSecurity.Open( iBTMan ) ); User::LeaveIfError( iSdp.Connect() ); User::LeaveIfError( iSdpDb.Open( iSdp ) ); User::LeaveIfError( iSocketServ.Connect() ); CActiveScheduler::Add( this ); CheckBluetoothL(); }
The CheckBluetoothL() function uses an instance of the RNotifier class to check whether the power is switched on. Some session handles provide an extended notier server that provides support for plug-in notiers. The notiers are useful for checking the status of a device or a connection, for example. The used plug-in notier is identied by a unique identier (UID), given as a parameter to
362
the asynchronous StartNotifierAndGetResponse() function. It is also possible to send and receive data from the notier by using the same function. In the example below, we send a boolean value and store the result in the iNotifierResult member variable:
void CBTServer::CheckBluetoothL() { // Make sure the Bluetooth module is powered on TPckgBuf<TBool> pckg; User::LeaveIfError( iNotifier.Connect() ); iNotifier.StartNotifierAndGetResponse( iStatus, KPowerModeSettingNotifierUid, pckg, iNotifierResult ); iStateMachine = EStateCheckingBluetooth; SetActive(); }
After an asynchronous service request and SetActive() call, it is up to the active scheduler to decide which RunL() function is called. The function shows us the order of actions in the Bluetooth server. First, the result of the Bluetooth device status is checked in the CheckedBluetoothL() function, as shown in the next example. After that, the device drivers are loaded. The interface to the Bluetooth device uses the serial communications. Thus, rst physical and logical device drivers for the serial port are loaded and the Serial communications server is started, if it is not already running. The function is omitted in the following, because it is similar to that in previous examples:
void CBTServer::RunL() { switch( iStateMachine ) { case EStateCheckingBluetooth: CheckedBluetoothL(); LoadDriversL(); ReserveLocalChannelL(); RegisterBTMan(); break; case EStateRegisteringSecurity: RegisteredBTManL(); ConnectSdpL(); ConnectSocketServerL(); WaitForConnectionL(); break;
SOCKET SERVER case EStateAcceptingConnections: ReadSizeL(); break; case EStateReadingSize: ReadDataL(); break; case EStateReadingData: ProcessDataL(); break; }
363
} void CBTServer::CheckedBluetoothL() { // Bluetooth module is now checked on iNotifier.CancelNotifier( KPowerModeSettingNotifierUid ); iNotifier.Close(); User::LeaveIfError( iNotifierResult[0] ); }
The ReserveLocalChannelL() function is used to allocate an available port to a new service. The reservation can be made with socket options. The used option gets the next available RFCOMM server channel, as seen below:
void CBTServer::ReserveLocalChannelL() { // Reserve a local channel for us to use iLocalChannel = 1; // To init channel TInt port = 0; RSocket socket; TProtocolDesc pInfo; User::LeaveIfError( iSocketServ.FindProtocol( pInfo ) ); KRFCap(),
User::LeaveIfError( socket.Open( iSocketServ, KRFCap ) ); User::LeaveIfError( socket.GetOpt( KRFCOMMGetAvailable ServerChannel, KSolBtRFCOMM, port ) ); iLocalChannel = STATIC_CAST( TUint8, port ); socket.Close(); }
Next, the service is registered to the Bluetooth security manager. For each service in the manager, service UID, protocol, and channel IDs are stored. The service UID is used to identify the service. The protocol
364
ID identies the protocol layer below the service. For most Bluetooth services, this is RFCOMM. The protocol ID is specied as a Bluetooth socket level options constant, for example KSolBtRFCOMM. The channel ID identies the port (channel), on which the service is running. There are three possible security settings, depending on whether an incoming service requires authentication, authorization, or encryption:
void CBTServer::RegisterBTMan() { TBTServiceSecurity serviceSecurity( TUid::Uid (KRPSServiceId), KSolBtRFCOMM, iLocalChannel ); serviceSecurity.SetAuthentication(EFalse); serviceSecurity.SetEncryption(EFalse); serviceSecurity.SetAuthorisation(EFalse); serviceSecurity.SetDenied(EFalse); iSecurity.RegisterService( serviceSecurity, iStatus ); iStateMachine = EStateRegisteringSecurity; SetActive(); }
In addition to the Bluetooth security manager, a new service is also registered to the SDP database. For each service there is a service record with service-specic attributes in the database. Each attribute has an ID, a type, and a value. The types and some attribute IDs are predened. Some universal attributes are dened in the btsdp.h: service record handle, service class ID list, service record state, service ID, protocol descriptor list, and so on. Complex attributes can be formed through lists of attributes. The lists can themselves contain lists of attributes. Attribute types may be boolean, data element alternative (DEA), data element sequence (DES)1 , integral, nil, string, an unsigned integer, or an URL(universal resource locator). A key attribute is the service class. Each service is an instance of a service class, which provides an initial indicator of the capabilities of the server. In addition, it denes other attributes which may be or must be in the service record. One application may also have several services, in which case they are stored in separate service records. Each service record may have many service classes. The service classes must be specializations or generalizations of each other and be ordered from most derived to least derived. The CreateServiceRecordL() function creates a new service record with a single service class. On return, a handle to the created
1
SOCKET SERVER
365
record is provided. An unsigned integral value for the attribute is provided by the CSdpAttrValueUint class. Its NewUintL allocates and constructs a new instance of CSdpAttrValueUint. The UpdateAttributeL() function sets a new value to an attribute. In the example below, the service record state (ID = 0x02) is set to 0. The next attribute is updated in the same way. The protocol list has an ID value of 4 and its type is a data element sequence. The start of the list is indicated with the MSdpElementBuilder::StartListL() function, showing that the subsequent elements belong to the DES (or DEA). BuildDESL() adds a DES into the DES, and BuildUUIDL() adds the identier of the L2CAP protocol to the list. The next integer identies the used channel, which in this case is KRFCOMM. For RFCOMM we use the previously reserved channel:
void CBTServer::ConnectSdpL() { // Create an SDP record TBuf8<4> value1; TBuf8<4> value2; CSdpAttrValue* attrVal; CSdpAttrValueDES* attrValDES; // Set Attr 1 (service class list) iSdpDb.CreateServiceRecordL( KRPSServiceId, iSdpHandle ); // Set Attr 2 (service record state) to 0 value1.FillZ( 4 ); attrVal = CSdpAttrValueUint::NewUintL( value1 ); CleanupStack::PushL( attrVal ); iSdpDb.UpdateAttributeL( iSdpHandle, 0x02, *attrVal ); CleanupStack::PopAndDestroy(); // attrVal // Set attr 4 (protocol list) to L2CAP, and RFCOMM value1.FillZ( 4 ); value1[3] = KRFCOMM; value2.FillZ( 4 ); value2[3] = STATIC_CAST(TUint8, iLocalChannel ); attrValDES = CSdpAttrValueDES::NewDESL( 0 ); CleanupStack::PushL( attrValDES ); attrValDES ->StartListL() ->BuildDESL() ->StartListL() ->BuildUUIDL( TUUID( TUint16( KL2CAP ) ) ) ->BuildUintL( value1 ) ->EndListL() ->BuildDESL()
366
COMMUNICATIONS APPLICATION PROGRAMMING INTERFACE ->StartListL() ->BuildUUIDL( TUUID( TUint16( KRFCOMM ) ) ) ->BuildUintL( value2 ) ->EndListL() ->EndListL(); iSdpDb.UpdateAttributeL( iSdpHandle, 0x04, *attrValDES ); CleanupStack::PopAndDestroy(); // attrValDES }
The server starts listening to the channel as in the case of any other application using the Socket server. After the connection has been established, data may be read and written using the Read() and Write() functions of the RSocket class:
void CBTServer::ConnectSocketServerL() { // Connect to the socket server TProtocolDesc pInfo; // Open a socket iListenSocket.Open( iSocketServ, KRFCap ); // Set up address object TBTSockAddr addr; addr.SetPort( iLocalChannel ); User::LeaveIfError( iListenSocket.Bind( addr ) ); // Begin to listen User::LeaveIfError( iListenSocket.Listen( 2 ) ); }
Bluetooth Client
If the client knows that there is a Bluetooth device in its neighborhood and the remote device has a service in a specic port, the client can connect directly to the device. In the normal case, device discovery must be performed to nd any Bluetooth devices in the neighborhood. The ConstructL() function is similar to the corresponding function of the server, although the client does not need to connect to the Bluetooth security manager and SDP database. By looking at RunL() we see previously mentioned phases in the use of Bluetooth in the client side. We start by device and service discovery, after which the client connects to the server and starts transferring data. The last function call in the ConstructL() starts the device discovery:
void CBTClientEngine::RunL() { switch( iStateMachine )
SOCKET SERVER { case EStateDiscovering: DiscoveredRemoteL(); QueryRemoteL(); break; case EStateQueried: WaitForDataL(); break; case EStateConnecting: WriteDataL(); CloseRemoteL(); WaitForDataL(); break; } }
367
The DiscoverRemoteL() function tries to nd devices, that support the service that is requested. Device information is stored in an instance of the TBTDeviceSelectionParams class. The search is based on the device class or service disarray protocol (SDP) universally unique identier (UUID), whichever is used:
void CBTClientEngine::DiscoverRemoteL() { // Connect to the RNotifier User::LeaveIfError( iNotifier.Connect() ); // Look for devices with services with our UUID TBTDeviceSelectionParams filterParams; TBTDeviceSelectionParamsPckg fpPckg( filterParams ); TUUID targetServiceClass( KUUID ); filterParams.SetUUID( targetServiceClass ); // Start the notifier. The response will be in // iDiscoveryResponse iNotifier.StartNotifierAndGetResponse( iStatus, KDeviceSelectionNotifierUid, fpPckg, iDiscoveryResponse ); // Change the state iStateMachine = EStateDiscovering; SetActive(); }
The DiscoveredRemoteL() function simply cancels the notier and sets the remote address, in case it is valid:
368
void CBTClientEngine::DiscoveredRemoteL() { // Close the notifier iNotifier.CancelNotifier( KDeviceSelectionNotifierUid ); iNotifier.Close(); // If the result is not a valid Bluetooth address, // leave with KErrGeneral. Otherwise copy the address // of the remote device. if( iDiscoveryResponse().IsValidBDAddr() ) { iRemoteAddr.SetBTAddr( iDiscoveryResponse().BDAddr() ); } else { User::Leave( KErrGeneral ); } }
The nal state before connection establishment and data transfer is to query the service in the servers SDP database. An instance of CSdpAgent is used to make SDP requests to a remote device. SetRecordFilterL() sets the classes of service to query for. The result will contain records for services that belong to the classes listed in the lter. The lter is a UUID, which represents service classes. In the example below, the KUUID (constant UUID) value is 0x5021.
void CBTClientEngine::QueryRemoteL() { // Create agent. iSdpAgent = CSdpAgent::NewL( *this, iRemoteAddr.BTAddr() ); // Create a search pattern and add a service classes to it CSdpSearchPattern* list = CSdpSearchPattern::NewL(); CleanupStack::PushL(list); list->AddL( KUUID ); // Set the search pattern on the agent iSdpAgent->SetRecordFilterL(*list); // Get first search result: results in call back to this iSdpAgent->NextRecordRequestL(); // Advance the state machine iStateMachine = EStateQuerying; CleanupStack::PopAndDestroy(); } // list
The actual handling of the service record in the remote SDP database is taken care of by the NextRecordRequestCompleteL() function.
SOCKET SERVER
369
We stored values in the protocol list attribute in the server, so they should be readable in the client. An instance of CSdpAttrIdMatchList holds a list of attribute IDs that may be retrieved from a remote device:
void CBTClientEngine::NextRecordRequestCompleteL( TInt aError, TSdpServRecordHandle aHandle, TInt /*aTotalRecordsCount*/) { // We got a service record. if( aError != KErrNone ) { // Some error QueriedRemote(); } else { // Ask for the contents of the record // Create a match list CSdpAttrIdMatchList* matchList = CSdpAttrIdMatchList::NewL(); CleanupStack::PushL(matchList); // Add an attribute ID to get matchList->AddL( TAttrRange( KSdpAttrIdProtocolDescriptorList ) ); // Set the match list on the agent iSdpAgent->AttributeRequestL( aHandle, KSdpAttrIdProtocolDescriptorList ); CleanupStack::PopAndDestroy(); //matchList } }
AcceptVisitorL() is a virtual function that requests a callback to pass the attribute value. If there are attributes that are not lists (the type of an attribute is different from DEA or DES), the VisitAttributeValueL() function in MSdpAttributeValueVisitor is called. As a parameter, the attribute value object and type are passed. This is a useful way to enumerate and go through each attribute in a list:
void CBTClientEngine::AttributeRequestResult( TSdpServRecordHandle /*aHandle*/, TSdpAttributeID aAttrID, CSdpAttrValue* aAttrValue) { // We got the contents. Use an attribute // visitor to parse the results. if( aAttrID == KSdpAttrIdProtocolDescriptorList )
370
The implementation of the VisitAttributeValueL() function is given below; it is used to read the channel port number in which the service is available:
void CBTClientEngine::VisitAttributeValueL( CSdpAttrValue& aValue, TSdpElementType aType) { // This will be called for each attribute // received. It just waits for attributes // of certain type and parses them. // All other attributes are ignored. TUUID rfcomm( TUint16( KRFCOMM ) ); switch( aType ) { case ETypeUUID: iPreviousUUID = aValue.UUID(); break; case ETypeUint: if( iPreviousUUID == KRFCOMM ) { iRemoteChannel = aValue.Uint(); } break; default: break; } }
Finally, the attribute request has been completed. We simply call the QueriedRemote() function, which updates the state of the state machine:
void CBTClientEngine::AttributeRequestComplete( TSdpServRecordHandle /*aHandle*/, TInt aError) { // Request complete. Announce that were done // to the state machine. QueriedRemote(); } void CBTClientEngine::QueriedRemote() { // Just advance the state machine
ETel SERVER iStateMachine = EStateQueried; // Continue immediately SetActive(); TRequestStatus* status = &iStatus; User::RequestComplete( status, KErrNone ); }
371
16.3.7
WAP
The Series 60 Platform provides access to a WAP 1.2.1 stack. Through API, it is possible to access wireless session, transaction, or datagram protocols (WSP, WTP, and WDP, respectively). The WAP stack is used in the same way as the other communications servers in Symbian OS; rst, a session to a WAP server is created. Note that this means a session to the WAP server in Symbian OS, not the WAP server serving WAP requests in the network. The session is created using the RWAPServ class. The naming analogy to Serial and Socket servers is obvious. The Connect() method creates the session. Unlike the corresponding methods of the Serial and Socket servers, this method also starts the server, if it is not already running. There is a common class (RWAPConn) from which all subsession classes are derived. This base class supports operations that may be used for connections in all WAP stack layers. WDP access is provided by the RWDPConn, and WSP access is provided by either RWSPCOConn (connection-oriented session) or RWSPCLConn (connectionless session). The bearer used by the WAP stack is selected by using the communications database. The protocol stack of the bearer, such as SMS or IP, are plug-in protocol modules. The WAP API is used by application engines using or providing WAP services. Nokia (2001h) has published a guide to WAP service development. This publication is very useful not only to application developers but also to WAP service developers.
16.4
ETel Server
The telephony server of Symbian OS is called ETel. It provides an interface and client-side API to telephony hardware. The user is not dependent on the vendor, because all applications use the standard API. The client-side session to the server is provided by the RTelServer class, which supports analogous functions to those of the Serial and Socket servers, in order to load telephony modules (LoadPhoneModule()), enumerate phones (EnumeratePhones()), and to get information on the specied phone (GetPhoneInfo()). In addition to
372
RTelServer, the client-side API provides three classes: RPhone, RLine, and RCall. RPhone provides functions to answer and initiate lines, query phone and line status and capabilities, access phone-based information such as GSM phonebooks, pass active calls between one another, support messaging such as SMS, and register to receive phone event notications. RLine provides access to the functionality of lines. These include line capability and status queries and event notications associated with the line. Calls are established and disconnected using the RCall class. In addition to call control functionality, this class enables queries on call capabilities, call status, different bearers, and call progress. An important function is LoanDataPort(). It allows a client to gain control of the port used to communicate with the modem. The client can send data directly to the port. While the client is using the port, the ETel server queues any commands which it has to the modem. The control shifts back to the ETel server when the RecoverDataPort() function is called:
CCallEngine::CreateCallL() { _LIT(KTsyName, "PhoneTsy.tsy"); _LIT(KDataLineName, "Data"); _LIT(KTelNumber, "+350401234567890"); TInt ret; RPhone phone; RLine line RCall call; ret = iServer.Connect(); User::LeaveIfError( ret ); ret=server.LoadPhoneModule( KTsyName ); User::LeaveIfError( ret ); ret = iServer.GetPhoneInfo( 0, phoneInfo ); // of phone User::LeaveIfError( ret ); ret = phone.Open( iServer, phoneInfo.iName ); User::LeaveIfError( ret ); ret = line.Open( phone, KDataLineName ); User::LeaveIfError( ret ); ret = call.OpenNewCall( line ); User::LeaveIfError( ret ); // Dial out to remote number entered by user ret = datacall.Dial( iStatus, KTelNumber );
// Number
ETel SERVER User::LeaveIfError( ret ); call.LoadDataPort(); HangUpDataCall(); call.Close(); line.Close() phone.Close(); iServer.Close() }
373
16.4.1 Fax
ETel supports fax services through three APIs: fax client, fax store, and header line API. The fax client API is used to send and receive fax messages, the fax store API includes services to store and retrieve fax information, and the header line API supports generation of the header line on the top of fax page. The architecture of the ETel faxing is shown in Figure 16.2. The fax printer driver creates the required fax pages, which are stored as a fax store le. This fax information is then taken from the le and passed by the fax client to ETel, which sends the fax. The fax message-type module (MTM) creates a header line data le, which is used by ETel to create a header line to add to the top of every page sent. The persistent settings are stored in the communications database component.
Fax MTM
Fax store
CommDb
RFax
Etel
374
16.5 Summary
The communications architecture of Symbian OS and the Series 60 Platform enables not only easy expandability of the communication system but also an easy means of programming. Each server provides a client-side API, which is used almost in an identical way to the server. In addition, if a protocol implementation changes, but the used server is the same, there are only small changes to the use of the protocol. In this chapter we have provided examples of how to use the client-side APIs of the Serial communication, Socket, and Telephony servers. We have emphasized the rst two servers because application developers do not use the Telephony server directly. The interested reader may nd out more on the Telephony server in Jipping (2002), which contains a very through description of any communications programming in Symbian OS. We have not yet discussed the Message server yet. The message server is the subject of the next chapter.
17
Messaging
Messages are self-contained data objects that are transferred between messaging applications. There are numerous types of messages, but most of them share some common features. Each message has a header, body, and zero or more attachments. The message header contains the source and the destination of the message and perhaps a time stamp showing when it was transmitted. The content of the message is included in the message body, and it is meaningful only to those programs (or to a user) that may use the message. Attachments can be arbitrary binary or textual data. Messages are delivered according to the pull or push model. In the pull model, messages are stored in the server, from which the messaging client downloads the received messages. In the push model, the server contacts the receiver directly and pushes the message to it. In this chapter, the messaging architecture of Symbian OS and the Series 60 Platform is described. In general, all message types are supported with a set of plug-in modules. The supported types include e-mail, short and multimedia messages, fax, and BIO (bearerindependent object) messages. All these message types and the use through the application programming interfaces (APIs) of the plug-in modules are described.
17.1
Messaging Architecture
Symbian OS implements a powerful, extensible framework for multiprotocol messaging. The messaging architecture consists of the message server and layered implementations of different messaging protocols that are implemented as message-type modules (MTMs). Series 60 has support for a short message service (SMS), a multimedia message service (MMS), e-mail, BIO messages (smart messaging),
376
MESSAGING
infrared, Bluetooth, and fax, although fax is typically used through the Telephony server (ETel). New protocols can be added to the framework, and it is possible to nd out at runtime which message types are supported in the device. The design also allows generic message access, the execution of certain operations, and the extraction of the same information from all message entries without knowing their type. For sending messages with use of different protocols, Symbian OS has an easy-to-use Send As API. A user interface (UI) is also available for the Send As in Series 60 (SendUI); SendUI encapsulates the whole message-sending process, including the required UI components, such as progress dialogs and menu items. SendUI and its usage will be introduced later in this chapter, in Section 17.6. The messaging framework is presented in Figure 17.1. The abstract MTM base classes are supplied by Symbian, as are the message server and the session object. Other modules visible in the gure can be implemented by third parties. Symbian delivers concrete MTMs for the message types mentioned earlier. Application means, for example, a message editor implementing UI functionality or any other application that uses the messaging subsystem. The purpose of each component is presented in this chapter. The basic type in messaging is an entry. An entry is an abstraction of the message or part of the message that is stored in the message
UI Data MTM Base
Application
UI MTM Base
Session
Concrete UI MTM
Message Server
Figure 17.1
MESSAGING ARCHITECTURE
377
server. For example, one short message is always one message entry, but multimedia messages and e-mails can have multiple entries, since attached objects are entries as well. Entries are created by the messaging engine when a message is received or created. Also, folders and services (e.g. mailbox, SMS service-centre address) are stored as entries. All entries are identied by a unique identier (UID) and they can be retrieved by using this UID. The header le msvids.h denes the identiers for common folders and services such as the local Inbox and Outbox. Entries can be retrieved by opening a session to the message server and using a constructor of CMsvEntry or the services of a session object. The classes that are used to access the entries are as follows: CMsvEntry, which is dened in msvapi.h, encapsulates the actions to create, manipulate, move, delete, and access the entries. It is of rather a heavyweight class, since it caches information about its children entries as well. CMsvServerEntry, dened in msventry.h, is similar to CMsvEntry, but it is used by server MTMs only. TMsvEntry from msvstd.h encapsulates the index entry and can be used to obtain information, such as size and type of the message. There are protocol-specic derivations of this class such as TMsvEmailEntry and TMmsMsvEntry. Changes to TMsvEntry are not written directly into the message server; they must be committed by using the CMsvEntry::ChangeL(const TMsvEntry&aEntry) method. The message server is a standard Symbian OS server that accepts asynchronous requests from clients. Its main responsibilities are controlling access to message data, delegating operations to modules implementing messaging protocols, and assuring that message data are consistent. Temporary, exclusive access to message data can be given to a requester. Access can consist of either reading or writing; multiple readers are allowed access to one message entry at a time. The server stores messages as dictionary le stores in the le system of the device. Every entry has at least two streams, which store body text and a backup copy of the entrys index data. Usually, the MTM creates additional streams to store information about recipients, settings, and other protocol-specic data. Generally, there is no need to use services provided by the message server directly; instead the MTMs may be used. Clients communicate with the message server using session objects that are instances of the
378
MESSAGING
CMsvSession class. Every client owns exactly one session instance. As mentioned earlier, entries can be retrieved by using the services of CMsvSession. The following example show how to open a session to the message server, access entries, and count the total size of the messages in Inbox:
#include #include #include #include #include <msvapi.h> <msvstd.h> <msvids.h> <msvuids.h> <e32base.h> // // // // // CMsvEntry, MMsvSessionObserver CMsvEntrySelection KMsvGlobalInBoxIndexEntryId KUidMsvMessageEntry CBase
// Observer needed to connect server, derived from MMsvSessionObserver class CMySessionObserver : public MMsvSessionObserver, public CBase { public: void HandleSessionEventL(TMsvSessionEvent aEvent, TAny* aArg1, TAny* aArg2, TAny* aArg3); }; void CMySessionObserver::HandleSessionEventL(TMsvSessionEvent aEvent, TAny* aArg1, TAny* aArg2, TAny* aArg3) { switch (aEvent) { // close session if something wrong with server case EMsvGeneralError: case EMsvCloseSession: case EMsvServerFailedToStart: case EMsvServerTerminated: User::Exit(KErrGeneral); break; default: // Do nothing break; } } TInt CountSizeOfMessagesInInboxL() { TInt size(0); // total size of the messages // Create session observer CMySessionObserver* observer = new(ELeave) CMySessionObserver; CleanupStack::PushL(observer); // Open session to message server CMsvSession* session = CMsvSession::OpenSyncL(*observer); CleanupStack::PushL(session); // Create object defining grouping, ordering and if invisible // entries are included into folder entry to be retrieved TMsvSelectionOrdering order(KMsvNoGrouping, EMsvSortByNone,ETrue); // Retrieve entry representing Inbox CMsvEntry* inboxEntry = CMsvEntry::NewL(*session, KMsvGlobalInBoxIndexEntryId, order); CleanupStack::PushL(inboxEntry);
MESSAGING ARCHITECTURE
379
// Get list of message entries in Inbox, folders are not included CMsvEntrySelection* selection = inboxEntry>ChildrenWithTypeL(KUidMsvMessageEntry); CleanupStack::PushL(selection); // Count size of the messages const TInt count(selection->Count()); for (TInt i = 0; i < count; i++) { // access message entry TMsvEntry messageEntry; TMsvId owningServiceId; User::LeaveIfError(session->GetEntry((*selection)[i], owningServiceId, messageEntry)); // size of the entry is in TMsvEntry::iSize size += messageEntry.iSize; } // Delete selection, inboxEntry, session and observer CleanupStack::PopAndDestroy(4); return size; }
Protocols are implemented as MTMs that implement general and protocol-specic functionality. General actions include creating, editing, and deleting messages. Usually, editing and viewing are implemented by separate dynamic link libraries (DLLs) to reduce the memory footprint and complexity of the MTM. An example of protocol-specic functionality is the ability to fetch one attachment from a mail server to the device by using the Internet Mail Access Protocol version 4 (IMAP4) MTM. This functionality is not supported by the Post Ofce Protocol version 3 (POP3) mail protocol or by its MTM. There are four types of MTMs: UI MTM handles message editing, viewing, folder manipulation, and connection handling. It also displays progress information and error messages. UI data MTM provides icons and menu items for the message type. These are not included in UI MTM, to make actions lighter. The client-side MTM handles address lists and subject, when appropriate, creates reply and forward messages, validates messages, and manages the MTM-specic data in the message store. The server-side MTM copies messages between local and remote folders, handles messages in remote servers, interprets entry data to and from the protocol presentation, and manages interaction with transport components, such as sockets and ETel. Messaging applications use mainly UI MTMs, UI data MTMs, and client-side MTMs to handle entries. If the user interface is not needed,
380
MESSAGING
all functionality is available in the client-side MTM. Owing to UI dependencies, UI MTMs and UI data MTMs must be adapted to the UI style used; client-side and server-side MTMs are generic technology used in all UI styles. The MTMs are loaded into the memory when needed by using services of the MTM Registry. The loading of an MTM is shown later in the SMS example (Section 17.3). The registry keeps count of instantiated MTMs and automatically unloads modules that are not needed again immediately in order to save memory. Unloading can be delayed to prevent sequential loading and unloading; appropriate timeout depends on the use of the protocol. For example, instant messaging MTMs are needed regularly, and messages need a fast reaction time, so they can always be kept loaded, whereas fax modules can be unloaded immediately, because they are probably rarely used. New message types can be added to the device by implementing and installing the relevant MTMs. If the protocol does not need user interaction, only the client and server modules are needed. Installation to the device is possible, for example, by using an SIS (symbian installation system) le. The new message type must be registered with the message server by storing some basic data about the MTMs, such as UIDs and a humanreadable name to be shown in Send via menus of the applications using SendUI. Also, the ordinals of the factory methods in the DLLs are registered so that the MTM classes can be instantiated. Prior to Symbian OS v 6.1, a le containing the required registration information was generated either by using the mtmgen utility and setting a le or by externalizing the CMtmGroupData object. In Symbian OS v 6.1 and subsequent versions, the MTMs can also be registered by writing a resource le that is compiled by using a resource compiler. Benets achieved by using the resource le are localization, version control, and easier registration le generation. The resource denition is in the mtmcong.rh le. The registration le syntax for messaging types requiring client-side and server-side MTMs is shown in the following example:
#include <mtmconfig.rh> // Resource definition #include "mymtmuids.h" // UIDs for MTM RESOURCE MTM_INFO_FILE { mtm_type_uid = KMyProtocolUid; // this differentiates // protocols technology_type_uid = KMyMessageTypeUid; components = { MTM_COMPONENT { human_readable_name = "My server MTM";
MESSAGING ARCHITECTURE
component_uid = KUidMtmServerComponentVal; specific_uid = KMyServerMTMUid; entry_point = 1; // factory method ordinal version = VERSION { major = 1; minor = 0; build = 100; }; }, MTM_COMPONENT { human_readable_name = "My client MTM"; component_uid = KUidMtmClientComponentVal; specific_uid = KMyClientMTMUid; entry_point = 3; // factory method ordinal version = VERSION { major = 1; minor = 0; build = 100; }; } }; }
381
The technology-type UID given in the denition tells the messaging type to which the MTM belongs. For example, all e-mail MTMs [IMAP4, POP3, and simple mail transfer protocol (SMTP)] have the same technology type, but different MTM-type UIDs. The BIO messaging types have a very similar resource for their registration. When the registration le is generated either by compiling the resource, using mtmgen, or externalizing a CMtmGroupData object, it is copied to the \system\mtm directory. An installation program that calls CMsvSession::InstallMTMGroup with a path to the created registration le as the argument must be run after the les are copied. This adds the MTM to the registry le maintained by the message server. Finally, the message server must be restarted before the installed module can be used. All steps can be done in the installation program, so the process is not visible to the user. The MTMs are uninstalled in a similar way, by rst calling CMsvSession::DeInstallMTMGroup() and then removing the les copied into the device during installation. The user-dened observers can be registered to be notied about events relating to entries of the message server. MMsvSessionObserver provides an interface to react to events sent by the message server. The example shown above had a simple implementation of this interface. All messaging applications implement this interface, since it is needed when a session to the message server is established. The interface consists of one method, the argument of which indicates an event. Notied events include message server shutdown an indication to close the session, and entry creations and deletions. For a full list of notied events, see the documentation of MMsvSessionObserver. MMsvEntryObserver provides an observer interface to entries. Notication is sent, for example, on entry creation, deletion, and movement. The observed entry may be a folder, and, in this case, notications are received from all events having that folder as the
382
MESSAGING
context. Thus, it is possible, for example, to observe all incoming short messages by dening the observer for the Inbox folder and reacting to messages that are short messages.
17.2 E-mail
Series 60 messaging supports all common e-mail protocols: POP3, IMAP4, and SMTP. Secure connections to servers implementing the feature are available for all protocols. The sending of e-mail is possible from any application by using the SendUI interface. Symbian OS supports MIME (multipurpose Internet mail extension) encoding for created and received messages. What differentiates e-mail from SMS and MMS is the concept of remote mail servers. SMS and MMS messages are received directly into the device, and there are no copies of the message elsewhere. E-mail messages are received into the remote e-mail server, and the device has only a snapshot of a certain situation in the mail server. Thus, it is possible that the device has messages that are deleted from the server and that the server has new messages that are not synchronized with the device. It is necessary to implement e-mail clients in order to handle such situations. Before the e-mails can be created or read, one or more e-mail accounts must be created. This is done by creating two services into the message server one for sending mail via an SMTP account and another for receiving messages via a POP3 or IMAP4 account. The account entries have their own stores into which the settings are saved. The SMTP account is always invisible; only the receiving service is shown to the user. Sending and receiving services are linked to each other by storing the identier (ID) of the opposite service into the iRelated member variable of the TMsvEntry of the service. Thus, the sending service can be restored from iRelated of the POP3 or IMAP4 service entry, and the receiving service is found in iRelated of the SMTP service entry. E-mail has its own entry type dened, TMsvEmailEntry, which is derived from TMsvEntry. This class provides access to such features as Will new messages include a signature or Vcard? and Is message formatted as plain text or HTML? IMAP4 ags are accessed and modied using this class. E-mail messages can be modied by using the CImHeader and CImEmailMessage classes. CImHeader encapsulates the header information, such as recipient, sender, subject, and date information about the message. CImEmailMessage is used to access and modify the body text and attachments of the message.
383
17.2.1
Sending E-mail
New e-mail messages can be created by using the CImEmailOperation class. It provides static methods to create new messages, replies, and forwarded messages. In the following example, a new e-mail message is created into the local drafts folder and lled with the sender, recipient, subject, and body text:
void CExampleAppUi::CreateAndSendMailMessageL() { // message parts that are created TMsvPartList partList(KMsvMessagePartBody | KMsvMessagePartAttachments); // message attributes, define that message is in preparation TMsvEmailTypeList typeList(KMsvEmailTypeListMessageInPreparation); // create wrapper object to synchronize operation CMuiuOperationWait* wait = CMuiuOperationWait::NewLC(); // create mail message CImEmailOperation* operation = CImEmailOperation::CreateNewL( wait->iStatus, // reports progress of the operation iSession, // pointer to CMsvSession object KMsvDraftEntryId, // folder into which message is created KMsvNullIndexEntryId, // SMTP service, using // default service partList, // defines message parts to be created typeList, // the kind of message created KUidMsgTypeSMTP); // the protocol the message is using CleanupStack::PushL(operation); wait->Start(); // this waits for completion of // create operation // next find out id of the new message TMsvId id; TPckgC < TMsvId > paramPack(id); const TDesC8& progress = aOperation.FinalProgress(); paramPack.Set(progress); CleanupStack::PopAndDestroy(2); // wait, operation // get created message CMsvEntry* entry = CMsvEntry::NewL(iSession, id, TMsvSelectionOrdering()); CleanupStack::PushL(entry); // restore message header and set recipient and subject CMsvStore* store = entry->ReadStoreL(); CleanupStack::PushL(store); CImHeader* header = CImHeader::NewLC(); // set own information as sender header->SetFromL(_L("Tester <[email protected]>")); // add recipient to recipient array header->ToRecipients().AppendL( _L("[email protected]")); // set subject header->SetSubjectL(_L("Test mail message"));
384
MESSAGING
// commit changes header.StoreL(store); CleanupStack::PopAndDestroy(); // header // create body text CImEmailMessage* message = CImEmailMessage::NewL(id); CleanupStack::PushL(message); // create richtext object using default formatting CRichText* richText = CRichText::NewL(EikonEnv-> SystemParaFormatLayerL(), iEikonEnv-> SystemCharFormatLayerL()); CleanupStack::PushL(richText); _LIT(KTestMailMsg, "Hello world!"); richText->InsertL(0, KTestMailMsg); // Insert body text wait = CMuiuOperationWait::NewLC(); message->StoreBodyTextL(id, richText, wait->iStatus); wait->Start(); // wait for completion CleanupStack::PopAndDestroy(5); // wait, richText, // message, store, // entry }
The above example execution is stopped in order to wait for asynchronous message creation and body text insertion. This will affect the responsiveness of the applications, and this technique should be used with care. An easier way to do the same thing is to use the Send As interface, which is described later in this chapter (Section 17.6). Like all e-mail interfaces, CImEmailMessage provides an asynchronous interface. Before an e-mail can be sent from the device, an SMTP service must be dened. The service stores all default settings for the created messages in the CMsvStore stream, and these settings are represented by the class CImSmtpSettings. This class encapsulates the information about user identication, secure connections, e-mail address, scheduling, and signature attachment. The settings can be stored and restored by using the StoreL() and RestoreL() methods of CImSmtpSettings. Some preferences can be changed on a per message basis, so a message can be sent using different settings from those dened for the used service. Such settings include, for example, scheduling, receipt request, and signature attachment. It must be noted, though, that not all e-mail clients support changes to all attributes. Scheduling settings enable the message to be sent immediately, opening a new network connection if needed, during the next connection or at the users request. The created messages can have any supported character set used in the header and body texts. One can dene whether the message use MIME encoding or not. The body text can be in plain text only, MHTML only, or both. Encoding and the body text character set can be dened for a single message in the mailbox. CImSmtpSettings
385
provides access to set the default values for the service, and, by using the methods of CimEmailMessage, it is possible to alter the settings for the message. CImHeader has methods for setting the header character set. Symbian OS v 6.1 also has a new class for the settings, TImEmailTransformingInfo. A TImEmailTransformingInfo object can be associated with a service when it is used as a default value for all new messages, or it can be associated with a single message. The class has getters and setters for all mentioned attributes concerning character sets and message encoding. The advantages of using TImEmailTransformingInfo is that all conversion and encoding information is stored in one place in which they can be easily accessed and modied.
17.2.2
Receiving E-mail
E-mail messages can be received from the mail server into the device by using POP3 and IMAP4. Messages are never retrieved to the device automatically; the operation must be initiated by user action or by other means, such as a timer. The fetching of messages is possible with use of CImPop3GetMail or CImImap4GetMail APIs. These classes are not meant to be used directly; rather, they are used through the client MTMs, which use the above-mentioned APIs. Usually, when a new message is received into the e-mail server, the header information is fetched during the next connection and the whole message is fetched on the users request. It is also possible to restrict the number of headers to be fetched to reduce network trafc, when an IMAP4 mailbox is used. This is done by using the SetInboxSynchronizationLimit() method of the CImImap4Settings object related to the mailbox. SetMailboxSynchronizationLimit() is used to control how the other folders compared with Inbox are synchronized. The header information includes sender and receiver, subject, size, character set, encoding, and information about the attachments. Attachments can be fetched from the server on demand, one by one if IMAP4 is used (POP3 does not support this). The messages fetched can be deleted from the device and left on the server, or deleted from the device and the server. Settings for receiving e-mail are dened by using the CImPop3Settings and CImImap4Settings classes. The settings are used and stored as SMTP settings, discussed in Section 17.2.1. The classes encapsulate settings, such as is secure connection used?, What is the login name?, What is the password?, and What are the synchronization preferences?. There are no settings per message; there is no need for them as there were with SMTP messages.
386
MESSAGING
Both protocols implement the ofine queue to which operations made ofine are appended. The most common operation queue is the deletion of a message. When a connection to the server is opened, all operations in the queues are executed.
17.3 SMS
SMS enables the transfer of short messages (160 characters, at the most, of 7-bit text, or 140 bytes of 8-bit binary data) to and from a mobile phone, even while a call is in progress. The 8-bit messages are often used for smart messaging in addition to 8-bit text. The 16-bit messages of 70 characters or less are used for Unicode (UCS2) text messages for Chinese and Arabic characters, for example. Unlike e-mail, SMS uses a push model to deliver the messages. The messages are stored in the SMSC (short message service center) and immediately pushed to the receiver, if it is attached to the network. Otherwise, the messages are stored in the SMSC for a specied time (e.g. 24 hours), to wait for delivery to the receivers phone. SMS can be used in either a text or PDU (protocol data unit, or protocol description unit) mode. When the text mode is used, a 160-character text message is encoded in binary format. There are several encoding alternatives, the most common of which are 88591, PCDN, PCCP437, IRA, and GSM (global system for mobile). In the PDU mode, binary data can be transmitted as such. The PDU mode (binary mode) enables the use of custom character coding. For example, with 5-bit coding one can send a message containing 224 characters at maximum. There are four PDU types dened in the SMS relay protocol. The relay protocol is a part of the SMS service of the GSM network: SMS-SUBMIT is used for sending short messages. SMS-DELIVER is used for receiving short messages. The PDU type changes from SMS-SUBMIT to SMS-DELIVER after transmission. SMS-STATUS-REPORT is used for sending queries about submitted but not yet delivered short messages, which are stored in the SMSC. SMS-COMMAND PDU type is used for indicating the status of a previously submitted short message to the sender (e.g. conrmation of a successfully delivered short message). In addition to the textual or binary contents, the SMS PDUs have a user data header. The header contains the sender and the receiver addresses (phone numbers), as well as the address of the SMSC through which the message was delivered. Other elds are used to store the
SMS
387
time stamp, message class, concatenation information, and application port addressing. The header takes up the rst 7 bytes of user data, which leaves 133 bytes for the content, or 128 bytes in case of a concatenated SMS message (www.forum.nokia.com). In the header, the time stamp eld indicates when the message was submitted from the senders device. The class eld of the header is used to indicate one of the four classes to which the message may belong. Class 0 or a ash message is used to activate the SMS indicator, but the message is not stored in the receivers phone. Class 1 is used for standard text messages, stored in the phones memory. Class 2 messages are stored in the memory of the SIM card. Class 4 messages are stored in an external device (e.g. in the PC, if it is connected to the phoneline). Several messages may be concatenated together, in which case the concatenation information denotes, for example, the number of message PDUs concatenated together. The application port addressing is used to deliver the message to the correct application. For example, smart messages contain no sensible information to be shown in the receivers SMS viewer.
17.3.1
388
MESSAGING
CClientMtmRegistry* mtmReg; mtmReg = CClientMtmRegistry::NewL( *session ); CleanupStack::PushL( mtmReg ); // Create a client-side SMS MTM object CBaseMtm* mtm = mtmReg->NewMtmL( entry->Entry().iMtm ); CleanupStack::PushL( mtm ); mtm->SetCurrentEntryL( entry ); CleanupStack::PopAndDestroy(3); // entry, mtmReg, mtm
The CMsvEntry class accesses the particular entry in the Message server. A TMsvEntry object is used to represent an index of the message in the server. The SMS-specic parts of the message are handled by means of the SMS MTM. Generic elds, such as the destination address, may be set by using the virtual functions of CBaseMtm, but SMS-specic elds are accessed through the CSMSHeader class. In addition to the header elds described above, other settings include delivery methods, handling of special messages, and SMS bearer options. The SMS MTM is used to access the standard message parts (i.e. the header and the body) in an SMS-specic way:
// Insert the contents of the message CRichText& mtmBody = mtm->Body(); mtmBody.Reset(); _LIT(KTestSmsMsg, "Hello world!"); mtmBody.InsertL( 0, KTestSmsMsg ); // Insert body text newEntry.SetInPreparation( EFalse ); // Preparation done newEntry.SetSendingState( KMsvSendStateWaiting ); newEntry.iDate.HomeTime(); // Set time to home time entry->ChangeL(newEntry); // To handle the sms specifics SmsMtm used CSmsClientMtm* smsMtm = static_cast< CSmsClientMtm* > ( mtm ); CleanupStack::PushL( smsMtm ); // Cache changes of header fields and header options smsMtm->RestoreServiceAndSettingsL(); // CSmsHeader provides access to SMS header fields CSmsHeader& header = smsMtm->SmsHeader(); CSmsSettings* sendOptions = CSmsSettings::NewL(); CleanupStack::PushL( sendOptions ); // Restore existing settings sendOptions->CopyL( smsMtm->ServiceSettings() ); // Set send options sendOptions->SetDelivery( ESmsDeliveryImmediately ); header.SetSmsSettingsL( *sendOptions ); CleanupStack::PopAndDestroy(2); // sendOptions and smsMtm // Set destination address _LIT(KDestinationAdd, "+35899876543210") smsMtm->AddAddresseeL( KDestinationAdd );
SMS
// Commit the cached changes smsMtm->SaveMessageL();
389
Now, the message is ready for sending. First, it is stored in the Outbox from which it is sent to its destination:
// Move message to the Outbox // Handle to a parent entry CMsvEntry* parentEntry = CMsvEntry::NewL(*session, newEntry.Parent(), TMsvSelectionOrdering()); CleanupStack::PushL(parentEntry); // Move original message from the parent to the Outbox // create wrapper object to synchronize operation CMuiuOperationWait* wait = CMuiuOperationWait::NewLC(); // create SMS message CMsvOperation* op = parentEntry->MoveL( newEntry.Id(), KMsvGlobalOutBoxIndexEntryId, wait->iStatus ); CleanupStack::PushL( op ); wait->Start(); // this waits completion of create operation TMsvLocalOperationProgress prog= McliUtils::GetLocalProgressL( *op ); User::LeaveIfError( prog.iError ); id = prog.iId; // Id of the moved entry CleanupStack::PopAndDestroy(4); // op, wait, parentEntry, // CCommandAbsorbingControl
390
MESSAGING
CBaseMtm* smsMtm = iMtm; // Add entry to task scheduler TBuf8<1> dummyParams; CMuiuOperationWait* wait = CMuiuOperationWait::NewLC(); CMsvOperation* op= smsMtm->InvokeAsyncFunctionL( ESmsMtmCommandScheduleCopy, *aSelection, dummyParams, wait->iStatus); CleanupStack::PushL( op ); wait->Start(); CleanupStack::PopAndDestroy(2); // wait, op }
Again, an asynchronous function is used. The function ScheduleCopy schedules the message to be sent through the Telephony server.
17.3.2
MMS
// be called) CMsvOperation* op = parentEntry->DeleteL( msvEntry.Id(), wait->iStatus ); CleanupStack::PushL( op ); wait->Start(); CleanupStack::PopAndDestroy(4); // smsMtm, parentEntry, // op, wait, } }
391
17.4
MMS
Using the SMS it is possible to deliver tones and simple black-andwhite pictures up to 72 28 pixels in addition to 160-character text greetings. MMS, the multimedia message service, is a new technology to deliver multimedia content between terminals (Nokia, 2001d). The content may be a picture, data, text, audio, or video. MMS is implemented on top of WAP 1.2, as shown in Figure 17.2, which describes the MMS architecture (WAP Forum, 2001). Instead of WAP, HTTP may also be used, allowing the use of MMS also in Java applications in the Series 60 Platform. The MMS Proxy relay delivers multimedia messages to the destination MMS server, which stores the message for later forwarding. In a typical network architecture, the Proxy relay and MMS server are implemented in the same network component, the multimedia message service center (MMSC).
MMS terminal Wireless network WAP gateway Internet or intranet MMS Proxy relay
Payload HTTP
Figure 17.2 Multimedia message server (MMS) architecture. Note: HTTP, hypertext transfer protocol; WAP, windows application protocol
Compared with SMS, the MMS delivery model is more complicated. There are six MMS PDUs: M-Send, M-Notication, M-Retrieve, M-NotifyResp, M-Acknowledge, and M-Delivery. In addition, WSP (Wireless Session Protocol) messages are used. PDUs also have different types (request, indication, response, and conrmation), which were described in Chapter 15. The M-Send.req and M-Retrieve.conf PDUs have a normal message structure, which consists of a header and a body. All other PDUs contain only the header part.
392
MESSAGING
Originator M-Send.req
MMSC
Receiver
Originator
MMSC M-Send.req
Receiver
M-Send.conf
M-Notification.ind
M-Send.conf
M-Notification.ind
Figure 17.3 Immediate and postponed delivery of an multimedia message. Note: MMSC, multimedia message service center; WAP, window application protocol; WSP, wireless session protocol
The MMS PDUs are transmitted in the content section of WSP or HTTP messages over the circuit-switched data (CSD) or General Pachet Radio System (GPRS) connection. The use of messages in two different scenarios is shown in the sequence chart in Figure 17.3. First, the sender uses a WSP POST request to send M-Send.req, which contains also the content or the body of the message. If the MMSC receives the message properly, it replies with a WSP POST response, containing an M-Send.conf PDU, to the sender. This is, in principle, similar to sending a short message. However, the message is not delivered immediately to the receiver; rst, a notication is sent using WAP PUSH (sent as an SMS) containing an M-Notication.ind message. The receiver may accept the message, postpone it, or discard it. The receiver uses a WSP GET request and response having the M-Retrieve.conf message to get the sent message from the MMSC. The received message is acknowledged with a WSP POST request containing either the M-NotifyResp.ind or M-Acknowledge.req PDU, depending on whether the message was delivered immediately or after a time delay. The MMSC conrms message delivery to the sender by using WAP PUSH, including an M-Delivery.ind message (WAP Forum, 2002a).
17.4.1
MMS
393
The header of each MMS PDU starts with the same parameters, which should be given in this order: X-Mms-Message-Type, which denes the PDU, (e.g. M-Send.req); X-Mms-Transaction-ID, which identies the M-Send.conf PDU and the corresponding M-Send.req; X-Mms-MMS-Version, which is currently 1.0. Other parameters in the header depend on the PDU type. A complete description is given in WAP forum (2002b). As mentioned, there are only two PDUs that have the body in addition to the header: M-Send.req and M-Retrive.conf. The contenttype denition is the last part of the header and is either application/vnd.wap.multipart.related and application/vnd.multipart.mixed. The former content type is used if the content is going to be presented to the user. Thus, there must be presentation instructions included in the message. The instructions are typically dened in SMIL (synchronized multimedia integration language), which is based on XML (extensible markup language). The latter content type is used in messages, the content of which is not shown to the user, in which case no SMIL part is needed. An example MMS message is as follows:
Content-type: application/vnd.wap.mms-message ... X-Mms-Message-Type: m-send-req X-Mms-Transaction-ID: 0 X-Mms-Version: 1.0 Date: 1026453567 From: 10.10.0.0/TYPE=IPv4 To: +35840123456789/TYPE=PLMN Subject: Test message X-Mms-Expiry: 1026539967 X-Mms-Priority: High Content-type: application/vnd.wap.multipart.related; type="application/smil"; start="<0000>" ... Content-type: application/smil
Content Presentation
The content is presented with the SMIL language, which supports the presentation of timed multimedia objects and animation. There are several SMIL proles, which dene a collection of modules to some application domain. The modules, in turn, dene the instructions the way in which multimedia objects are presented or, more formally,
394
MESSAGING
they dene the semantics and syntax for certain areas of functionality. Some dened modules concern layout, timing, synchronization, and animation. The presentation instructions and presentable objects are packaged in the same MMS PDU. The message content contains pointers [e.g. URLs (universal resource locators)] to the presented objects (Nokia, 2002). SMIL support is still quite limited in the Series 60 Platform. Currently, it is possible to present slide shows using SMIL, but, for example, a video clips lasting several minutes are not yet supported. Each slide may have at most one image and one piece of text shown on the screen. Additionally, the message may contain played or spoken sound. The layout of the slide is presented using SMIL. In SMIL, <par>and</par> tags are used to indicate objects that should be presented at the same time. Similarly, <seq>and</seq> tags are used to indicate the sequential order of presentation. The image and the text in one slide may be shown in parallel, but it is impossible to present two slides at the same time. The <body> tag is the sequence time container. Each slide is a parallel time container, which enables the parallel presentation of slide content. The example below shows an example of the MMS PDU body. The layout species that the upper part of the screen is reserved for the image and the lower part for the text. There are two slides, shown in sequence: one from Rome and another from San Francisco. Both slides contain image and text. Additionally, a sound clip is played during both slides:
<smil> <head> <layout> <root-layout width="160" height="140"/> <region id="Image" width="160" height="100" left="0" top"0"/> <region if="Text" width="160" height"40" left="0" top="100"/> </layout> </head> <body> <par dur="60s"> <img src="rome.gif" region="Image"/> <text src="rome_greetings.txt" region="Text"/> <audio src="rome.amr"/> </par> <par dur="60s"> <img src="san_francisco.gif" region="Image"/> <text src="san_fancisco.txt" region="Text" /> <audio src="san_francisco.amr" /> </par> </body> </smil>
SMART MESSAGING
395
Supported Contents
The smallest maximum size of the multimedia message supported by several device manufacturers is 30 kB (CMG et al., 2002). The MMS Conformance document (CMG et al., 2002) species the minimum set of content formats that devices must support. The Series 60 Platform supports additional formats too. In principle, the content may be of any MIME type. Thus, in addition to actual multimedia messages, it is possible to send Nokia ring tones, vCard and vCalendar objects, Symbian OS application and Java application installation packages, WML (wireless markup language) content, or third-party le formats. Supported picture formats are JPEG with JFIF exchange format, GIF87a, GIF89a, and Windows BMP. In addition to these, Nokia 7650 supports animated GIF89a and png image formats, sent in JPEG. For audio, AMR format is supported. Nokia 7650 supports also WAV, with ADPCM, PCM, aLaw, Law, and GSM 6.10 encodings. For text us-ascii, utf-8, and utf-16 is supported. A complete list of supported contents can be found in (CMG et al., 2002).
17.5
Smart Messaging
Smart Messaging is a Nokia proprietary concept for sending and receiving special messages, (e.g. ring tones, picture messages, operator logos, and business cards) over SMS. Infrared and Bluetooth are also supported as bearers. As the messaging is bearer-independent, applications can communicate with a wide variety of handsets. The smart messaging architecture is extensible and enables application developers to design and implement new kinds of message types. The most common smart message types are documented in the Smart Messaging Specication, is available at www.forum.nokia.com. In order to support a new kind of smart message, the following things need to be done: implement a BIO information le; dene the message format; implement the plug-in viewer component that plugs into the SMS Viewer; the same viewer is used for infrared and Bluetooth smart messages; implement functionality into the viewer for decoding and validating the message content; implement functionality for a special command, (e.g. Save to MyApp or Play).
396
MESSAGING
In the following, we use the same rockpaperscissors (RPS) game example as in earlier chapters to demonstrate the implementation of a new smart message type. The smart message type is used for playing the game over SMS.
#include <biftool.rh> #include "rpsviewer.loc" RESOURCE BIO_INFO_FILE { message_type_uid = 0x0FFFFFFB; message_parser_uid = 0x0FFFFFFD; message_app_uid = KUidUseDefaultApp; message_appctrl_uid = 0x0FFFFFFC; file_extension = ".rps"; description = "Rock, paper & scissors"; icons_filename = "none"; icon_zoom_levels = {1}; ids= { ID { type = EWap; confidence = ECertain; port = 9500; }, ID { type = ENbs; confidence = ECertain; text = "RPS msg"; }, ID { type = EIana; confidence = ECertain; text = "text/rps" } }; }
SMART MESSAGING
397
The eld message type uid is the UID for the smart message type. Received smart messages are stamped with the type when they are created in the Inbox by the framework. The UID should be obtained in the same way as normal application UIDs. The eld message parser uid is used for some built-in smart message types. You should set it to NULL. The message app uid should have the value KuidUseDefaultApp. This means that the SMS Viewer application with a plug-in viewer is used. Another application cannot be used because of architecture reasons. The UID of the plug-in viewer DLL is specied in message appctrl uid. The file extension eld is optional. The smart messaging framework itself does not use it. The description eld denes the Inbox header. This description can be localized in the standard way because the BIF is a resource le. The values of the icons filename and icon zoom levels elds do not have any effect in the Series 60 Platform. The supported sending and receiving ways are dened by an array of ID blocks. Each ID block denes a possible way of receiving or sending the message. When sending, the rst suitable block for the chosen bearer is used. This means that you can control the sending method for a bearer by placing the appropriate block rst in the array. The most common way of sending and receiving smart messages is to use the narrow band socket (NBS) port number in the user data header of the short message. This is done by using the type EWap and a port number. The EWap also makes possible the receiving of messages with an old legacy-style NBS text header. If the received message is to be recognized using textual tags, the ENbs type (Symbian OS enumeration for NBS) should be used. In this case, the text eld is used instead of the port number. The NBS port number space is controlled by Nokia. For IR and Bluetooth smart messaging, the IANA type is used. The MIME type must be dened in the text eld. An Apparc recognizer with the same MIME type must exist so that the message will be sent correctly.
398
MESSAGING
opponents response back to the challenger. We call the rst message sent by the challenger a challenge message, and a response to that from the opponent a response message. The challenge message contains the message identier, challenger name, and his or her moves. The identier is used to distinguish between different challenges. The player name is an optional eld. The moves are encoded as integers so that rock is represented as 0, paper as 1, and scissors as 2. When the opponent has received the message and played the game, the results will be sent back to the challenger. The response message contains the original ID, challenger name, and his or her moves and, in addition, to these it will contain the responder name and his or her moves. The message format is as shown in Figure 17.4.
Msg-id Chal-name Chal-moves Resp-name Resp-moves
Suppose we have two players, Joe and Tom. At rst, Joe challenges Tom, and the message might have the following content: 1307 Joe 002. Tom accepts the challenge and plays the game. When the game is nished the response is sent back to Joe and the message content might now be: 2005 Joe 002 Tom 102.
SMART MESSAGING CMsvSession* aSession, TMsvld ald, TMsgBioMode aEditorOrViewerMode, const TFileName& aFileName);
399
There are a number of abstract methods from MMsgBioControl that should be implemented. Many of these are related to layout management and command handling. The SetMenuCommandSetL() method allows menu options to be added dynamically. The framework calls it every time that the Options menu is opened. In our example, we have the play option in the received message view. The IsEditor() method is used for asking whether the control was launched in the sending or received mode:
void CRpsBioControl::SetMenuCommandSetL( CEikMenuPane& aMenuPane) { const TInt KMenuPos = 1; // The inserting position // of menu item. if (IsEditor()) // is sending view? { // no special commands when sending } else { // view of received msg AddMenuItemL(aMenuPane, R_RPS_PLAY, KMenuCommandPlay, KMenuPos); } }
The HandleBioCommandL() function is the command handler, which you should implement if you have added your own commands in SetMenuCommandSetL():
TBool CRpsBioControl::HandleBioCommandL(TInt aCommand) { // Get the real command id. TInt commandId = aCommand iBioControlObserver.FirstFreeCommand(); if (commandId == KMenuCommandPlay) { PlayGameL(); return ETrue; // the command was handled } return EFalse; // the command was not handled }
There are a number of specialized methods inherited from MMsgBioControl which are used for scrolling by the framework. Some
400
MESSAGING
of them have a default implementation, which will do if your view is small enough. CRichBio is a text control which is tailored for the plug-in viewer scrolling framework. It has the same look and feel as the built in smart message viewers, for example the Business Card smart message viewer. Note that the CRichBio cannot be fully constructed until there is a parent with a window. It means that CRpsBioControl should override SetContainerWindowL(), and construct the CRichBio there after calling SetContainerWindowL from CCoeControl:
void CRpsBioControl::SetContainerWindowL( const CCoeControl& aContainer) { CCoeControl::SetContainerWindowL(aContainer); // constructed here because parent with window needed iViewer = CRichBio::NewL(this, ERichBioModeEditorBase); AddFieldsToViewerL(*iViewer); }
The CRichBio has a number of layout methods which also exist in MMsgBioControl or CCoeControl. Most of these calls can be passed on from the CRpsBioControl to the CRichBio instance, for instance the SetAndGetSizeL():
void CRpsBioControl::SetAndGetSizeL(TSize& aSize) { iViewer->SetAndGetSizeL(aSize); SetSizeWithoutNotification(aSize); }
The other calls which are passed straight from CRpsBioControl to the CRichBio instance are listed below:
CurrentLineRect() VirtualHeight() VirtualVisibleTop() IsCursorLocation() OfferKeyEventL()
401
Note that smart messages can be sent from the device by using either SendUI or SendAs. The APIs have an argument for specifying the smart message type.
17.6
SendUI
SendUI offers a simple API to create and send messages, using different messaging protocols from the applications. SendUI is built on top of the Send As API, which is included in Symbian OS generic technology. The interface is implemented by the CSendAs class. SendUI is implemented by the CSendAppUi class, and it offers the whole message creation and sending process, including all UI components, such as the menu items shown in the applications and progress dialogs during sending. Both interfaces provide a means to query the sending capabilities of the message type. For example, if a document needs to be sent as an attachment, message types supporting the body text only can be ignored. CSendAs provides a common interface to create a message, using any message type installed in the device. An application using Send As must implement the MSendAsObserver interface, which is called by CSendAs to gain more information on the required sending capabilities and to render the message in the correct format for sending. Most messaging protocols do not use this interface at all. One exception is fax MTM, which calls the interface to render the material in a suitable format for sending as a fax. The available message types can be queried at runtime, or the message type can be dened in the application. Although the constructor of Send As does not take TRequestStatus as a parameter, and the call to the constructor returns immediately, some initialization is done asynchronously, and the created object is not ready to be used immediately. Thus, it is recommended that the Send As object not be created immediately before it is needed, but, for example, during application launch. The following example sends the le given as a
402
MESSAGING
parameter as an attachment to the recipient. The used message type is queried from the user by showing a list of the available message types supporting attachments:
#include <sendas.h> #include <baflutils.h> // CSendAs // BaflUtils::CopyFile
void SendMessageL(const TDesC& aRecipientAddress, TFileName aMessage, MSendAsObserver& aObserver) { // create Send As object CSendAs* sendAs = CSendAs::NewL(aObserver); CleanupStack::PushL(sendAs); /* message needs to support attachments, no need to examine capabilities further, so 2nd argument EFalse, if 2nd argument is ETrue, MSendAsObserver::CapabilityOK() is called */ sendAs->AddMtmCapabilityL(KUidMtmQuerySupportAttachments, EFalse); // show list of available MTMs to user, who selects preferred // message type const TInt selected(QueryMtmL(sendAs->AvailableMtms());
// use selected mtm and create message sendAs->SetMtmL(selected); sendAs->CreateMessageL(); // create attachment into entry and copy file into directory // returned by CreateAttachmentL TMsvId attachmentId; TFileName directory; sendAs->CreateAttchmentL(attachmentId, directory); RFs rfs; rfs.Connect(); CleanupClosePushL(rfs); User::LeaveIfError(BaflUtils::CopyFile(rfs, aMessage, directory)); CleanupStack::PopAndDestroy(); // rfs
// add recipient to message sendAs->AddRecipientL(aRecipientAddress); // validate message, particularly recipient syntax for the chosen // message type is verified if (sendAs->ValidateMessage() != 0) { // message is not valid, handle error } // move message to outbox sendAs->SaveMessageL(); CleanupStack::PopAndDestroy(); // sendAs } TInt QueryMtmL(const CDesCArray& aMtmArray) {
SendUI
// show selection list to user ... return selectedMtm; }
403
In the above example, it was the responsibility of the user of the API to implement the required user interface. Series 60 includes SendUI, which is built on top of Send As and implements a user interface in conforming to the platform standards. Like CSendAs, the constructor of CSendAppUi returns immediately, but the created object is not usable immediately. For creating messages, SendUI has two methods,
CreateAndSendMessageL()
and
CreateAndSendMessagePopupQueryL()
SendUI offers two overloads of the CreateAndSendMessageL() method for creating messages. The rst overload is called with a command ID of the SendUI menu item, and the other is called with the UID of the MTM of the wanted message type. CreateAndSendMessagePopupQueryL() shows a query list box of available message types, and the user can select which message type is used. The previous example can be written by using SendUI in shorter and simpler form using the latter method:
#include <sendui.h> // CSendAppUi
void SendMessageL(const TDesC& aRecipientAddress, TFileName aMessage) { // argument is 0, were not using UI // if UI is used, argument indicates place of the Send menu item // in applications menu CSendAppUi* sendUi = CSendAppUi::NewLC(0); // create array containing attachment(s) CDesCArrayFlat* attachments = new (ELeave) CDesCArrayFlat(1); CleanupStack::PushL(attachments); attachments->AppendL(aMessage); // create array containing recipient(s) CDesCArrayFlat* recipients = new (ELeave) CDesCArrayFlat(1); CleanupStack::PushL(recipients); recipients->AppendL(aRecipientAddress); // create message, SendUI shows list from where message type is // selected, default values are used for some parameters // The 1st argument is title shown in popup query sendUi->CreateAndSendMessagePopupQueryL(_L("Send message"), TSendingCapabilities::ESupportsAttachments,
404
MESSAGING
NULL, // no body text attachments, KNullUid, // not a BIO message recipients); CleanupStack::PopAndDestroy(3); } // sendUi, // attachments, recipients
SendUI also provides menu items to be used in the applications wishing to send information. The client application has to instantiate a CSendAppUi object, giving it an argument indicating the location of the menu items of SendUI in the applications menu. There must always be command IDs available after the identication given when creating SendUI; these are used for the menu items shown in the submenu. To show a menu item, DisplaySendMenuItemL() is called in the menu initialization method, when the menu is opened:
#include <sendnorm.rsg> // UI item constants void CExampleAppUi::DynInitMenuPaneL(TInt aMenuId, CEikMenuPane*aMenuPane) { switch (aMenuId) { case R_EXAMPLEAPP_MENU: { TInt pos; // find position for menu aMenuPane->ItemAndPos(ECmdSendUi, pos); /* insert menu item, 3rd argument defines requirements, if any, using TSendingCapabilities object */ iSendAppUi->DisplaySendMenuItemL(*aMenuPane, pos, TSendingCapabilities()); break; } ... } ... }
When the SendUI submenu is opened, DisplaySendCascadeMenuL() should be called in the menu initialization method:
void CExampleAppUi::DynInitMenuPaneL(TInt aMenuId, CEikMenuPane* aMenuPane) { switch (aMenuId) { ... case R_SENDUI_MENU: // Defined is sendnorm.rsg // show submenu, 2nd argument is an array of MTMs // which are not shown in list
SUMMARY
405
When a command is selected in the SendUI submenu, the command must be handled and the message created by using CreateAndSendMessageL(), giving it the selected menu item ID as an argument. The message is then created and opened embedded in the editor, if the message type uses the editor to create messages. When the editor is closed, control returns to the application which launched it.
17.7
Summary
The messaging architecture of the Series 60 Platform supports e-mail, short messages, multimedia messages, and smart messages. It is possible to implement new message-type (MTMs) modules to support other message types and protocols. Messages are accessed through the Message server, which provides an index of all messages, regardless of their type and other properties. Through the index it is possible to access a message header, but further manipulation typically requires message-type-specic plug-in modules. Message creation depends on the message type, but most message types contain a header, a body, and attachments. The header contains, at least, the receivers address and the subject. The body is most often written in the rich-text format. Attachments can be any binary data. In this chapter we have described how to use the services of the messaging architecture to create, send, and receive e-mail messages, short messages, and multimedia messages.
18
Connectivity
A broad denition for connectivity is the capability to connect and share information with the external world. Most household devices are still closed systems: stereos, TVs, and even standard phones do have limited data-sharing features. However, the tendency in modern society is to be more and more mobile-centric and information-centric. With the everincreasing demand to take notes, to get and send information instantly, while on the move around, the actual value of smartphones will be in the data they can store, not in the hardware itself. The data can be either personal or related to business, but given the precious information that smartphones contain, that data must be accessible at any time and in any place. Connectivity and synchronization make sure that the information is always available, secure, safely backed up, up to date, and can be shared with other people, devices, and services. Communication protocols enable connectivity, and connectivity enables a connection establishment and data change between Symbian OS phones and non-Symbian OS devices. There are two types of connectivity: local and remote. Local connectivity is short-range, device-to-device connectivity (e.g. to share business cards, or to allow direct desktop synchronization). Remote connectivity relates to data sharing and synchronization over the telephone network and/or the Internet between a smartphone and a server. SyncML is the industry-approved standard for remote connectivity. This chapter introduces Symbian Connect (a desktop interface from Symbian OS), SyncML, and synchronization, and device management in general. Specic emphasis is placed on connectivity capabilities used by Series 60 Platform.
SYMBIAN CONNECT
407
18.1
Symbian Connect
Symbian Connect is a component that provides features for desktop data synchronization and connectivity. For end users, Symbian Connect is a standard Windows application, giving direct access to device capabilities and data repositories when a connection is established. For developers, a Symbian Connect software development kit (SDK) provides a powerful tool for utilizing the connectivity services with C++ or Visual Basic and building their own plug-in engines and applications for synchronization, conversion, and task and le management. The rst Series 60 Connectivity release supports, in principle, all Windows versions from Windows 95 onwards, but full interoperability is guaranteed with: Windows 98 SE release; Windows NT service pack 3; if a Bluetooth connection is used, service pack 5.0 is required; Windows 2000; Windows ME.
18.1.1
Application installation [SIS les (Symbian installation system les) can contain Symbian OS executables, Java Midlets, audio, etc.]. Sync engine: this provides underlying sync technology for sync task drivers. Contacts and agenda synchronization: Agenda sync task driver: this provides agenda synchronization functionality for appointments, events, to-do lists, and
408
CONNECTIVITY
anniversaries, between Symbian OS Agenda and PC-based PIM (personal information management) applications (Microsoft Schedule+ 7.x , Microsoft Outlook 9x and 2000, Lotus Organizer 97, 97GS, 5.0 and 6.0). Contacts sync task driver: this provides contact synchronization between Symbian OS Contacts and PC-based PIM applications (Microsoft Schedule+ 7.x , Microsoft Outlook 9x and 2000, Lotus Organizer 97, 97GS, 5.0 and 6.0). Email synchronization: E-mail sync task driver: this provides e-mail synchronization functionality for e-mails between the Symbian OS Message Center and PC-based mail applications (Microsoft Outlook 9x and Microsoft Exchange client). Machine management: Symbian Connect recognizes a smartphone identier [ID; such as the International Mobile Equipment Identity (IMEI) code] and can seamlessly manage several devices from a single desktop. Backup data for each machine are stored in separate directory trees, with synchronization details and other settings also being held separately. The appropriate information is automatically invoked on connection; no user input is required, as all the procedures for multiple machine management are totally transparent. Capabilities manager: this is an engine module, determining the capabilities of the attached machine. Framework user interface: this is a completely new user interface for Symbian Connect, consisting of a frame window that contains the view plug-in functionality. View plug-ins: generally, these consist of an engine and a user interface (UI) component, which plug into the framework user interface. Control panel: this gives the user access to all the Symbian Connect settings from one place. The individual control panel items are applets that plug into the control panel. These are: connection, log settings, CopyAnywhere, machine manager, and le types. Error logger: this is an engine that allows for logging and viewing of errors and information messages within Symbian Connect. Task scheduler: this carries out a number of regularly scheduled tasks, including sync and backup. A Unify allows a selection of tasks to be run at a single click or cradle button press.
SYMBIAN CONNECT
409
Task drivers: these consist of an engine and property pages, and plug into the task scheduler component. File operations (supported by Symbian OS but not exposed in Series 60 by default) consist of: onboard conversion; le transfer; Explorer shell extension, allowing one to browse and to move, copy, convert, and delete les on the Symbian OS phone via Windows Explorer; CopyAnywhere, an engine that synchronizes the PC and the phone clipboards.
It is important to note that some Series 60 smartphones (such as Nokia 7650) are designed not to expose their le structure but automatically to handle all supported le types, such as images, music, or contact cards. The reason for this is to minimize the burden of learning and managing complex operations and to let the smartphone do everything automatically. Therefore, document-related operations (i.e. le management, remote print, and clipboard) are not necessarily supported as standard features. However, interfaces should be open for any third-party developer, so the application development is still enabled.
410
CONNECTIVITY
Task Capabilities Broadcast scheduler manager proxy Symbian Connect engine (ECengine.exe) TimeIS sync RTSocket Sync engines DNS mRAccess point mRouter RunTime mRouter WinSocket
Symbian OS to Win32 interface layer Symbian OS WINC component layer Symbian OS WINC engines Agenda Contacts Backup
Figure 18.1 High-level connectivity architecture. Note: DNS, domain name service
Symbian Connect architecture can be observed in different layers. The topmost layer is the UI layer, the interface visible to the end-user. It is highly customizable by the device manufacturer and has some plug-in framework for developers. The Win32 COM layer provides all the engines used by connection management, conversion, and synchronization and backup. The capabilities manager provides all the information on device parameters. Win32 COM engines are common to all Symbian OS phones; hence, it guarantees interoperability between Series 60 smartphones and other platforms. A step towards a non-Windows bind solution is to utilize a TCP/IP (transmission control protocol/Internet protocol) connection with DNS (domain name service) and RAS (remote access server). Symbian Connect is almost as much a Symbian application as it is a Windows application; a remarkable part of its internal workings is layered on top of the Symbian WINC variant. The WINC component layer provides a utilization of the non-UI parts of Symbian OS, which is available for PCs running an operating system compatible with Microsofts Win32 application programming interface (API). WINC allows a PC to use exactly the same application engines that run
SYMBIAN CONNECT
411
on a smartphone. A PC running Symbian Connect is able to use the facilities offered by two operating systems simultaneously. When a PC is connected to a standalone smartphone, two Symbian machines are actually connected together. The hard work of getting the data from one operating system to another is performed inside Symbian OS to the Win32 components. The interfaces are provided, for instance, to the Symbian Agenda and Contacts models.
Comparable methods are provided for C++ and Visual Basic in a straightforward and intuitive manner. For example, any program can be started on a smartphone by calling StartProgram() with the name and path of the program as a parameter. Most of the Symbian Connect engine calls are available in both synchronous and asynchronous forms, and multiple commands can be sent to the engine, with each command being held in a queue, until it can be processed.
412
CONNECTIVITY
Backup and restore functions are used to detect what machine is connected, to retrieve and use device-specic information, to set backup and archive directories, to analyze le differences, and to add specic les to the list of items to be backed up. Once everything is in place, a Backup() function performs all the operations requested. Backup covers contacts, calendar, documents, and installed components. Device and application settings are also backed up. For data protection and copyright reasons, certain les (such as MIDIs, JARs (Java archives), and Waves) are not saved to backup archive.
Connection Management
The Connection manager supervises connections between a PC (running Symbian Connect) and a Symbian OS smartphone, and it includes both PC-side and phone-side components. The evolution of connection management is described in the following. Symbian Connect 6.0 This provides the following:
Abstraction of the hardware connection layer away from the protocol layer; the Connection manager works in the same way over any physical layer it supports. Connections over physical serial links, infrared links, Bluetooth, and USB (universal serial bus) are supported. The minimum conguration for RS232 serial
SYMBIAN CONNECT
413
communications is a three-wire mode (using GnD, TxD, and RxD); however, RTS/CTS and DTR/DSR are supported when available. Support for multiple client applications on the PC: this is achieved by ensuring that all data transfers are atomic operations. The Connection manager can multiplex or demultiplex data to or from a Symbian OS-side custom server; thus a single instance of a custom server will support a number of client applications on the PC. Support for unify functionality: that is, it allows a selection of tasks (synchronization, backup, any user-dened tasks) to be started with a single click or cradle button press. Unify task can be triggered equally from the smartphone side or the PC side. Detect ion of unexpected disconnection of a phone and broadcast of the disconnection to all clients on the PC: this ensures that all custom servers open on the phone are shutdown. The broadcast of this information will occur within two seconds of detection. No restriction on the amount of data that can be sent to or retrieved from the phone. Symbian Connect 6.1 nectivity: This is the rst release with Series 60 con-
The PLP (Psion link protocol) connection protocol is replaced with mRouter, a protocol enabling connection management over a TCP/IP link. Access to connection parameters is through a connection icon in the Windows System Tray. Windows ME support is provided. Bluetooth with Serial Port Prole (serial link emulation) is supported. Architecture to add new connectivity protocols is available. Symbian Connect 7.0 USB support, Bluetooth LANP (local area network access prole) support. This offers:
414
CONNECTIVITY
protocol was for the most part not documented. In consequence, the only desktop platform supported was Windows, and there was never full connectivity implementation for Macintosh, Unix, or Sun. Some pioneers did reverse-engineer the PLP, but it was obvious that true interplatform solutions, beyond the simple le get and put operations, could not really exist before replacement of the PLP. Now, connectivity operations are not limited to the Windows or desktop end; they can easily be channeled to a network. The connection manager can now, for example, enable Internet browsing over Bluetooth or SyncML synchronization channeled directly to the server. A scenario where Symbian Connect applications can entirely reside somewhere on the network is now possible. Figure 18.2 illustrates the mRouter connection.
PC Symbian Connect apps custom svrs Symbian Connect engine mRouter COM interface Series 60 Platform Symbian Custom servers GenConnectivity server mRouter interface
mRouter (PPP server, AT command engine) BT plug IR plug Serial plug RS232 USB plug
Winsock plug
Virtual Comm
BT stack
MS IR stack
COM ports
BT PRT HCI
Figure 18.2 Connection over mRouter; for abbreviations, see the glossary
The mRouter protocol consists of components both on the Windows and on the Symbian OS side. Connection from the Series 60 side is established with Esocket, TCP/IP, and dialup networking architecture [Nifman (network interface manager) and PPP (point-to-point protocol)]. Access from the connectivity server to the utilization of infrared, Bluetooth, Serial, or USB is provided through the mRouter interface. Dual homing is used as a connection method. On the Windows side, similar components are provided when connecting the Symbian Connect engine to physical connection layers.
SYNCHRONIZATION
415
For end-users, the change of connection protocol is transparent, although the connection should be more reliable and will enable trustworthy connection over infrared, Bluetooth, and USB. For the developer, it opens a new world, with standard TCP/IP connections and easy-to-use APIs. The mRouter protocol provides the following APIs: connection/disconnection; permitting the developer to congure the connection, query the current conguration, and start or stop the connection; connection monitoring; with a callback function, information on connection progress is provided. The following parameters can be managed by the protocol: connection type [data routed via GPRS/CSD (General Packet Radio Service/circuit-switched data) or mRouter]; bearer [RS232C, IrComm, RFComm (Bluetooth), USB, Emulator, or unknown]; Bluetooth prole [SPP (serial port prole), LAP (local area network access prole), or DUNP (dialup networking prole)]; status of current connection (connecting, connected, disconnecting, disconnected).
18.2
Synchronization
Data Synchronization is the process of making two sets of data identical. (SyncML initiative 2002) In the mobile world, prediction of the future is like shooting at a moving target, with a lot of speculation, new trends, and prophecies. Still, there are denite trends that can be identied. A mobile user is a multiple-system user, relying on multiple devices, applications, and data, and shuttling between applications and systems. Typically, smartphone users create and edit content information through various PIM applications, or any application storing data on the device. Similar information is also kept on their PC or network repository. Rather than force the user to maintain two independent sets of data, synchronization allows the same data to be seamlessly maintained on both devices. Changes at each end must be kept synchronized. With the everincreasing dependence on constantly updated data, the synchronizing of data becomes a top-priority task. Synchronizing
416
CONNECTIVITY
the data between systems is a key element in the new mobile computing reality. Without proper synchronization, disparities in the application data damage user efciency and reduce users condence in the smartphone.
SYNCHRONIZATION
417
An example of vCard format is shown below: BEGIN:VCARD vCard header, a starting sequence of a single vCard record; one le can consist of several vCards VERSION:2.1 vCard version number; describes the vCard specication version in which the vCard is implemented REV:20020625T115241Z this property species the combination of the calendar date and time of day of the last update to the vCard object N:Smith;Ira;;; name property; can consist different name attributes (e.g. second name, title, marital status, etc.). ADR;HOME:;;37 Fulham Park Park Gardens;London;;SW6 4JX;UK address ORG:MedTwo Inc; organisation, employer TEL;VOICE:+44 2075632952 telephone number; different tags can be used for mobile, work, and home numbers EMAIL;INTERNET:[email protected] PHOTO;ENCODING=BASE64: . . . image data removed END:VCARD vCard ends e-mail address encoded image starts
Figure 18.3 illustrates how the same vCard object is displayed in a Series 60 phonebook. Data from the vCard object is rst parsed from the Unicode text format and converted to the Contacts database. Same contacts databases can be used in different language versions; only eld names will vary.
418
CONNECTIVITY
the le. Elements can be used in the control le to identify a pair of dynamically loadable ISynchApp interfaces. ISynch provides a single function, Synchronize(), that is called to perform the synchronization operation; the function can only be used within Symbian Connect. Since, in some cases, the synchronization operation can take time, ISynch provides an IProgress interface. It is used by the ISynchApp dynamic link libraries (DLLs) for each application to keep the user informed about the progress status and to report if any error occurs. Each synchronization starts by processing the control le. During this phase, the two ISyncApp application-specic interfaces are instantiated and initialized. The implemented virtual functions do most of the important synchronization work. Each ISynchApp has an Open() function, which is called to establish and validate its supported database. Following this, the CheckSource() function is used to verify the contents. The bulk of the synchronization is then performed by the two functions ReadSource() and WriteSource(). These functions convert the individual entries found in the database to and from the supported data types (vCard, vCalendar, or vMail).
18.3 SyncML
SyncML is an initiative for device synchronization standardization and will be supported by most of the synchronization service providers and
SyncML
419
handheld, smartphone, and traditional mass-market phone manufacturers. The SyncML initiative was formed in Paris, in February 2000, and the sponsor members are (September 2002) Ericsson, IBM, Lotus Development Corporation, Motorola, Nokia, Openwave Systems Inc., Matsushita Communication Industrial (Panasonic), Starsh Software, and Symbian. The sponsor members primarily fund the forum, and, on an equal basis, manage and steer the standard specication and interoperability processes. Currently, there are about 50 client and 30 server SyncML compliant products. In June 2002, the announcement of a new global organization the Open Mobile Alliance (OMA) was made. The alliance combines the forces of the WAP Forum, the Open Mobile Architecture Initiative, the SyncML initiative, Wireless Village initiative, the Location Interoperability Forum (LIF), and the MMS Interoperability Group (MMS-IOP). SyncML enables synchronization not only between a Symbian OS device and a PC but also between any device or service using SyncML. SyncML can bind to several bearer protocols. The supported bearers include HTTP (hypertext transfer protocol), WSP [wireless session protocol], OBEX [object exchange; IrDA (infrared data association), Bluetooth, and other local connectivity interfaces], pure TCP/IP networks, and proprietary wireless communications protocols. The SyncML protocol architecture is shown in Figure 18.4. The rst Series 60 SyncML version supports only a HTTP bearer. A fundamental of this gure is that equal synchronization layers are presented on both the smartphone side and the server side, and physical connection of different bearers can be used. SyncML supports arbitrary networked data. In order to guarantee interoperability, the protocol describes how common data formats are represented and transferred over the network. The introduction and plug-in capability of the new formats will ensure extensibility. Developers are also allowed to use their own experimental protocol primitives. The common data characteristics that a protocol should support include (SyncML Initiative, 2002): PIM data formats, such as vCard for contact information, vCalendar and iCalendar for calendar, to-do lists, and journal information; objects such as e-mail and Internet news; relational data; XML (extensible markup language) and HTML (hypertext markup language) documents; binary data, binary objects.
420
CONNECTIVITY
Synchronization server application Synchronization client application Synchronization client agent Synchronization server engine Synchronization server agent SyncML interface SyncML SyncML HTTP Internet or Intranet WSP WAP OBEX Transport IrDA, USB, RS, Bluetooth Physical medium SyncML interface
Smartphone
Server
Figure 18.4 High-level SyncML protocol architecture. Note: HTTP, hypertext transfer protocol; IrDA, infrared data association; OBEX, object exchange; RS, RS-232; USB, universal serial bus; WAP, wireless application protocol; WSP, wireless session protocol
By default, the Series 60 Platform supports vCard and vCalendar synchronization only, but in future the plug-in architecture will permit extension to the propriety data types. SyncML contains two protocols: one for device management and one for synchronization. There are several ways in which the synchronization operation can be performed (SyncML Initiative, 2002): two-way sync: a standard synchronization type, where a client and a server exchange information about modied data; slow sync: a form of two-way synchronization, where a client sends all items in the database to the server and the server does the synchronization analysis on a eld-by-eld basis; usually, this operation is performed only when synchronizing databases for the rst time; one-way synchronization from the client only: the client sends its modications to the server, but the server does not send its modications back; refresh synchronization from the client only: a client sends all its data from a database to the server, which replaces any existing data with that sent by the client; one-way synchronization from the server only: the client gets all modications from the server but the client does not send its modication to the server;
SyncML
421
refresh synchronization from the server only: the server replaces all the data in the client database; server alerted synchronization: the server alerts the client to start a specic type of a synchronization with it; this can be done via smart or BIO (bearer-independent object) messaging or by using the WAP PUSH operation.
422
CONNECTIVITY
Properties may be read and only a few of them (ACL, Name, and Title) may be replaced by the user. The device automatically updates the values of the other properties. The importance of device management will grow signicantly in the near future as mass volumes of smartphones become available. The effort individuals or corporate IT personnel are currently using for maintaining and conguring desktop PCs will be moving towards remotely operated device management. Operators or corporations need to control a large number of customers who have varying computing skills. It is fundamental that smartphones be accessed and supported remotely with as limited end-user intervention as possible. However, all device management operations should be safe and protected from illegal access to smartphone data.
18.4 Summary
The Series 60 Platform provides powerful connectivity tools for easy and straightforward data-sharing and synchronization with the external world. Predened functionality ensures safe backup and standard synchronization. The exible plug-in architecture and sound connection management and synchronization permit third-party developers to extend the connectivity experience and to make future innovations true. The Series 60 connectivity solution is a stepping-stone towards transition from PC-centric data storage and synchronization operations to where most is performed at the multiple mobile Internet locations. A smartphone users personal data must be always available, always connectable, always safe, and always synchronized.
Part 4
Programming in Java
19
Programming in Java for Smartphones
In addition to smartphones, ordinary mobile phones are starting to support Java. This chapter denes the principles of Java 2 Micro Edition, CLDC (connected limited device conguration) conguration, and MIDP (mobile information device prole) commonly used in mobile phones. In the next chapter, we go through the user interface (UI) programming framework of the MIDP application. The Series 60 Platform supports MIDP and provides some extensions for better device control and performance. Java is an object-oriented programming language developed by Sun Microsystems. It is designed to work on many different platforms. This is realized by execution of the same compiled source code, called byte code, in a virtual machine developed for a specic platform. In the Series 60 Platform, K virtual machine (KVM) is used. Originally, Java was developed for server and desktop computers, but it has evolved to survive in a low-resource mobile device environment (Allin, 2001). The strengths of the Java language in mobile device environment are portability, possibility to secure execution environment, and over the air deliverability to user devices.
19.1
426
J2ME is easy to learn for rst-time programmers, and it can easily be adopted by the experienced Java user. Java is already known for application and service development for desktop and server devices. The Java 2 Platform is separated into three editions to enable differentiation of the large variation in industry needs. Java 2 Standard Edition and Java 2 Enterprise Edition serve the traditional computer markets. For the emerging wireless market, Sun has added a third edition, the J2ME. Figure 19.1 shows the architecture of the Java 2 platform.
Optional packages
Optional packages Java 2 Platform, Standard Edition (J2SE Platform) JRE Java 2 Platform, Micro Edition (J2ME Platform) Personal profile Foundation profile MID profile CDC CLDC Java Card APIs
Figure 19.1 Java 2 Architecture. Note: API, application programming interface; CDC, connected device conguration; CLDC, connected limited device conguration; JRE, Java runtime environment
The editions of the Java 2 platform are: Java 2 Platform, Standard Edition (J2SE), for the desktop computer market; Java 2 Platform, Enterprise Edition (J2EE), for enterprises with scalable server solutions; Java 2 Platform, Micro Edition (J2ME), for the consumer market. All editions of the Java 2 Platform can be further adjusted to target use with optional packages. Optional packages contain software components and frameworks that enable application programmers to create high-functionality applications without inventing the wheel over and over again. The J2ME consists of congurations and proles to customize the runtime environment to the needs of the large variety of device types and different usage models. A conguration is the base runtime environment built from common application programming interfaces (APIs) and a virtual machine (VM) for a device category. From the application programmers point of view, Java binary code is always executed in the virtual processor
427
environment, called a virtual machine. The conguration denes the basic capabilities of the underlying VM and device such as memory resources and network connection. The conguration also describes the core set of software APIs. The next section, on connection limited device conguration, gives an example of the an API of the J2ME conguration. A conguration is extended by a prole for the vertical market. The prole species a set of APIs that address this market. Typically, a prole denes APIs for the UI framework and persistent data storage. The section on mobile information device proles (Section 19.3) presents an example of the J2ME prole used in the Series 60 Platform. An application developed for the Java 2 Platform will run on any device that complies with the same conguration and prole. The J2ME denes two device categories, specied in two different congurations: the connected device conguration (CDC) and the connected limited device conguration (CLDC). Figure 19.2 shows the components of J2ME architecture.
J2ME Profiles Personal Profile MID Profile Handheld Profile Java Card GSM Profile Open Platform Profile
Figure 19.2 Java 2 Micro Edition (J2ME) architecture. Note: CDC, connected device conguration; CLDC, connected limited device conguration; GSM, global system for mobile; JVM, Java Virtual Machine; KVM, K Virtual Machine; MID, mobile information device; VM, Virtual Machine
The CDC is for high-end consumer devices, such as set-top boxes and communicator phones. These devices have a large range of UI capabilities; the typical memory available to a Java application is around 24 Mbytes and a high-bandwidth network connection. In this category, high-bandwidth network is quite a broad term, because the bandwidth of a communicator device can be as low as 1550 Kbit s1 , but a set-top box might provide 2 Mbytes of bandwidth. The CLDC is for low-end consumer devices, such as mobile phones, two-way pagers, and personal organizers. The user interface is very simple; the minimum memory budget is typically around 128 Kbytes, and only a low-bandwidth network connection is available. As an extension to the CLDC, the Mobile Information Device Prole (MIDP) denes the APIs for the vertical mobile phone market.
428
Smartphones using the Series 60 Platform are equipped with the CLDC and the MIDP extension. The conguration and prole will be discussed in detail in the next section.
19.2.1 Requirements
CLDC denes a number of hardware requirements for the target device. The requirements are dened loosely to keep the door open for a broad range of devices. The memory requirements are: at least 128 kbytes of non-volatile memory (typically ash or ROM) for running the VM and the CLDC libraries; at least 32 kbytes of volatile memory (typically RAM) during application runtime. Note: there is no requirement that a device should support dynamic content or application downloading. However, most devices will support this feature. Additionally, the CLDC denes minimal software requirements. The underlying host operating system must be able to run the KVM and manage the applications on the device. Management of the applications includes selecting, launching, and removing those applications from the application manager.
19.2.2
Security
The design principles of the security model of the J2ME are simplicity and a low memory footprint. The simple sandbox model means that the applications are run in an environment where they can access only predened APIs and resources of the underlying device and VM. An application is treated somewhat like a child in a sandbox. The applications can do whatever they come up with within the sandbox, but they cannot harm the environment outside of the sandbox. Every
429
crossing of the sandbox edge is controlled and veried. Only an application from the same application suite can play in the same sandbox, thus helping to prevent applications from harming each other. The following features dene a simple sandbox security model: all downloaded class les must be veried, because hazardous byte code can break the VM and get access to closed APIs or resources; only a predened set of Java APIs are available to the application programmer; the application programmer cannot open new APIs or in any other way interfere with parts of the device that are advisedly closed because of security reasons; there is a class le look-up order; the application programmer cannot overwrite classes in the java.lang.* or javax.microedition.*, packages; Java application downloading and management is handled by native implementation, not the JVM; the application programmer cannot interfere with Java byte code downloading. J2SE features that are eliminated from J2ME MIDP because of security concerns are as follows: Java native interface (JNI): the simple sandbox security model provided by CLDC assumes that the set of native functions must be closed; user-dened class loaders: the sandbox security model requires elimination of user-dened class loaders, because all classes must be loaded by the system class loader; reection: the CLDC Java applications are not permitted to inspect the number or the content of classes, objects, methods, elds, threads, execution stacks, or other runtime structures inside the virtual machine; midlet cannot directly close the VM: the Exit() method of the Runtime and System classes will throw java.lang.SecurityException. The midlet can only notify the midlet execution environment that it is ready for shutdown. The MIDP Java application can access the resources belonging to the same midlet suite. The midlet suite is a collection of MIDP applications and their resource les. Section 19.3, on mobile information device prole, describes the midlet suite in more detail. Midlet can access resource les, such as images, that are packed inside the JAR (Java archive) le of the midlet suite. For storing the
430
state of the midlet and some other cached data, the midlet can create persistent storage les in nonvolatile memory of the device. If two midlets belong to the same midlet suite, they can access each others persistent storage les. To ensure that the removed applications do not leave any trash behind, all persistent storage les of the midlet suite will be erased when the midlet suite is uninstalled.
19.2.4
Packages Overview
The CLDC denes the basic set of packages that a wireless device must support. The classes included in the packages are in the
431
Table 19.1 Features of the Java Virtual Machine removed for the K Virtual Machine Compatibility with: Java language specication Floating point: processors of small devices typically do not have a oating point unit (FPU). Without a FPU, oating point operations are quite expensive in terms of computing time Finalization: removal of the nalization simplies the garbage collection process. Because of the limited nature of the CLDC, application programmers do not need to relay on nalization Error handling: exception handling is supported, but error handling is limited. First, recovery from serious error conditions is highly device-dependent and, second, implementing error handling capabilities fully according to the Java language specication is rather expensive Compatibility with the: Java Virtual Machine specication Floating point: Processors of small devices typically do not have an FPU. Without an FPU, oating point operations are quite expensive Java native interface (JNI): the simple security model of the CLDC assumes that the set of native functions must be closed. Full support of JNI would consume too many resources Custom class loader: the class loader cannot be replaced, overridden, or modied. The simple security model of the CLDC assumes that applications cannot override the default class loader. The class loader is device-dependent Reection: this is removed mainly because of resource limitations Thread groups: support for threads exists, but not for thread groups. Thread groups are removed because of resource limitations Finalization: removal of nalization simplies the garbage collection process. Because of the limited nature of the CLDC, application programmers do not need to relay on nalization Weak references: removal of weak references simplies implementation of the virtual machine and, particularly, the garbage collection process Errors: error handling capabilities are limited and device-dependent. First, recovery from serious error conditions is highly device-dependent and, second, implementing error handling capabilities fully according to the Java language specication is rather expensive
Note: CLDC, connected limited device conguration; Java language and virtual machine specication can be found in Steele et al. (2000) and Lindholm and Yellin (1999), respectively.
main derived from J2SE. Some classes have been redesigned; others are newly introduced for the CLDC. The packages are listed in Table 19.2. The classes in the packages can be grouped into J2SE-derived classes and CDLC-specic classes; these classes are introduced and special aspects highlighted in the following two subsections.
432
PROGRAMMING IN JAVA FOR SMARTPHONES Table 19.2 Connected limited device conguration (CLDC) packages Package java.util java.io java.lang javax.microedition.io Description Miscellaneous utility classes (based on J2SE) System input and output through datastreams (based on J2SE) Fundamental classes (based on J2SE) Networking support (CLDC-specic)
Table 19.3 Base classes of Java 2, Micro Edition Class java.lang.Class java.lang.Object java.lang.Runnable Comment Instances of the class Class represent classes and interfaces in a running Java application The Object class is the root of the class hierarchy The Runnable interface should be implemented by any class whose instances are intended to be executed by a thread Every Java application has a single instance of the Runtime class, which allows the application to interface with the environment in which the application is running. Note: the Exit() method will always throw the java.lang.SecurityException The System class contains several useful class elds and methods. Note: the Exit() method will always throw the java.lang.SecurityException A thread is a unit of execution in a program The Throwable class is the superclass of all errors and exceptions in the Java language
java.lang.Runtime
java.lang.System
java.lang.Thread java.lang.Throwable
Data-type classes Table 19.4 describes data types that can be used in J2ME. The table describes object forms of data types and also the corresponding primitive types that can be used. The biggest difference from J2SE primitives is that the J2ME does not have oat or double data types. Collection classes The J2ME supports basic collection types of the J2SE collection framework, as shown in Table 19.5. Inputoutput classes The J2ME supports basic Java inputoutput streams. Both byte and character-encoded streams are supported, as shown in Table 19.6.
CONNECTED LIMITED DEVICE CONFIGURATION Table 19.4 Class java.lang.Boolean java.lang.Byte java.lang.Character java.lang.Integer java.lang.Long java.lang.Short java.lang.String java.lang.StringBuffer Data types available in Java 2, Micro Edition Comment The Boolean class wraps a value of the primitive type boolean in an object The Byte class wraps a value of the primitive type byte in an object The Character class wraps a value of the primitive type char in an object The Integer class wraps a value of the primitive type int in an object The Long class wraps a value of the primitive type long in an object The Short class wraps a value of the primitive type short in an object The String class represents character strings A string buffer implements a mutable sequence of characters
433
Collection classes Comment An object that implements the Enumeration interface generates a series of elements, one at a time This class implements a hash table, which maps keys to values The Stack class represents a last-in, rst-out (LIFO) stack of objects The Vector class implements a growable array of objects
java.util.Enumeration
Internationalization Classes listed in Table 19.7 provide implementation for character-encoded streams. Calendar and time classes The J2ME supports date and time handling. The classes listed in Table 19.8 provide ways to handle date and time calculations, which would require many rules and code lines without these classes. Utility classes Table 19.9 lists the utility classes. Exception classes Table 19.10 describes exceptions that can be thrown by API methods of the CLDC.
Comment The DataInput interface provides an interface for reading bytes from a binary stream and reconstructing from them data in any of the Java primitive types The DataOutput interface provides an interface for converting data from any of the Java primitive types to a series of bytes and writing these bytes to a binary stream A ByteArrayInputStream contains an internal buffer that contains bytes that may be read from the stream This class implements an output stream in which the data are written into a byte array A data input stream lets an application read primitive Java data types from an underlying input stream in a machine-independent way A data input stream lets an application write primitive Java data types to an output stream in a portable way This abstract class is the superclass of all classes representing an input stream of bytes This abstract class is the superclass of all classes representing an output stream of bytes A PrintStream adds functionality to another output stream; namely, the ability to print representations of various data values conveniently An abstract class for reading character streams An abstract class for writing to character streams
java.io.DataOutput
java.io.Reader java.io.Writer
Table 19.7 Stream-handling classes Class java.io.InputStreamReader Comment An InputStreamReader is a bridge from byte streams to character streams: it reads bytes and translates them into characters according to a specied character encoding An OutputStreamWriter is a bridge from character streams to byte streams: characters written to it are translated into bytes according to a specied character encoding
java.io.OutputStreamWriter
Error classes The J2ME has limited error handling capabilities. The classes listed in Table 19.11 indicate serious error conditions. The VM may throw these errors or silently destroy the application. The applications are not required to recover from these errors.
MOBILE INFORMATION DEVICE PROFILE Table 19.8 Calendar and time classes Class java.util.Calendar Comment Calendar is an abstract class for getting and setting dates by using a set of integer elds such as YEAR, MONTH, DAY, and so on The class Date represents a specic instant in time, with millisecond precision TimeZone represents a time-zone offset, and also works out daylight savings
435
java.util.Date
java.util.TimeZone
Table 19.9 Utility classes Class java.lang.Math Comment The class Math contains methods for performing basic numeric operations An instance of this class is used to generate a stream of pseudo-random numbers
java.util.Random
Network classes and exception classes Classes listed in Tables 19.12(a) and 19.12(b) provide a framework for simple network connections. These connections can be used to make an HTTP (hypertext transfer protocol) request and read les. The CLDC does not provide any concrete implementations (the implementations are provided by proles).
19.3
Comment Signals that an end of le or end of stream has been reached unexpectedly during input Signals that an I/O operation has been interrupted Signals that an I/O exception of some sort has occurred Character encoding is not supported Signals that a malformed UTF-8 string has been read in a data input stream or by any class that implements the data input interface Thrown when an exceptional arithmetic condition has occurred Thrown to indicate that an array has been accessed with an illegal index Thrown to indicate that an attempt has been made to store the wrong type of object into an array of objects Thrown to indicate that the code has attempted to cast an object to a subclass of which it is not an instance Thrown when an application tries to load in a class through its string name using the forName() method in the Class class The class Exception and its subclasses are a form of Throwable that indicates conditions that a reasonable application might want to catch Thrown when an application tries to load in a class but the currently executing method does not have access to the denition of the specied class because the class is not public or in another package Thrown to indicate that a method has passed an illegal or inappropriate argument Thrown to indicate that a thread has attempted to wait on an objects monitor or to notify other threads waiting on an objects monitor without owning the specied monitor Signals that a method has been invoked at an illegal or inappropriate time Thrown to indicate that a thread is not in an appropriate state for the requested operation Thrown to indicate that an index of some sort (such as to an array, to a string, or to a vector) is out of range Thrown when an application tries to create an instance of a class using the newInstance() method in the Class class, but the specied class object cannot be instantiated because it is an interface or an abstract class
java.io.UnsupportedEncodingException java.io.UTFDataFormatException
java.lang.ClassCastException
java.lang.ClassNotFoundException
java.lang.Exception
java.lang.IllegalAccessException
java.lang.IllegalArgumentException java.lang.IllegalMonitorStateException
java.lang.InstantiationException
MOBILE INFORMATION DEVICE PROFILE Table 19.10 (continued ) Class java.lang.InterruptedException Comment
437
java.lang.RuntimeException
java.lang.SecurityException java.lang.StringIndexOutOfBoundsException
java.util.EmptyStackException java.util.NoSuchElementException
Thrown when a thread is waiting, sleeping, or otherwise paused for a long time and another thread interrupts it using the interrupt() method in the Thread class Thrown if an application tries to create an array with negative size Thrown when an application attempts to use null in a case where an object is required Thrown to indicate that the application has attempted to convert a string to one of the numeric types but that the string does not have the appropriate format RuntimeException is the superclass of those exceptions that can be thrown during the normal operation of the Java Virtual Machine Thrown by the security manager to indicate a security violation Thrown by the charAt() method in the String class and by other String methods to indicate that an index is either negative or greater than or equal to the size of the string Thrown by methods in the Stack class to indicate that the stack is empty Thrown by the nextElement() method of an Enumeration to indicate that there are no more elements in the enumeration
Table 19.11 Error classes Class java.lang.Error Comment An Error is a subclass of Throwable that indicates serious problems that a reasonable application should not try to catch Thrown when the Java Virtual Machine cannot allocate an object because it is out of memory, and no more memory could be made available by the garbage collector Thrown to indicate that the Java Virtual Machine is broken or has run out of resources necessary for it to continue operating
java.lang.OutOfMemoryError
java.lang.VirtualMachineError
438
Table 19.12 (a) Network classes and (b) exception classes Class (a) Network classes javax.microedition.io.Connection javax.microedition.io.ContentConnection javax.microedition.io.Datagram javax.microedition.io.DatagramConnection javax.microedition.io.InputConnection javax.microedition.io.OutputConnection javax.microedition.io.StreamConnection javax.microedition.io.StreamConnectionNotier javax.microedition.io.Connector (b) Exception classes javax.microedition.io.ConnectionNotFoundException Comment
This is the most basic type of generic connection This interface denes the stream connection over which content is passed This is the generic datagram interface This interface denes the capabilities that a datagram connection must have This interface denes the capabilities that an input stream connection must have This interface denes the capabilities that an output stream connection must have This interface denes the capabilities that a stream connection must have This interface denes the capabilities that a connection notier must have This class is a place holder for the static methods used to create all the connection objects This class is used to signal that a connection target cannot be found
MIDP applications
Native applications
Figure 19.3 presents the architecture of J2ME MIDP. The architecture supports three different kinds of applications. The native applications are run on top of the host operating system and are hostdevice-specic applications, such as the midlet application manager. MIDP applications are very portable because they can be run in any device that supports MIDP prole. Applications specic to the original equipment manufacturer (OEM) can typically provide more device-specic functionality than can pure MIDP applications because they can utilize OEM-specic APIs. For
439
example, Nokia UI API allows direct access to the UI resources of a Series 60 device. Utilization of OEM-specic APIs limits the applications to run only in devices of that manufacturer or even in some device group of that manufacturer.
19.3.1 Requirements
The MIDP denes its own requirements on top of the CLDC hardware requirements. It needs: 8 kbytes of nonvolatile memory for persistent data; at least a 96 54 pixel screen; availability of user input (through a keypad, keyboard, or touch screen); two-way networking with limited bandwidth. These requirements are satised in a typical mobile phone. Thus, mobile phones with Java MIDP capabilities are increasingly appearing on the market. Typical MIDP applications (midlets) used in these devices are simple games.
19.3.2
Package Overview
MIDP specic packages shown in Table 19.13 extend to the CLDC classes with user interface framework, midlet application framework and persistent storage classes. The user interface framework is designed to t in a small display and meet low resource allocation requirements. The application framework is simple sandbox application environment with persistent storage possibility. The persistent storage framework allows applications to create simple persistent record stores.
Table 19.13 Mobile information device prole (MIDP) packages Package javax.microedition.lcdui javax.microedition.midlet javax.microedition.io javax.microedition.rms Description Provides the user interfaces for MIDP applications MIDP applications and interactions Networking support Provides a mechanism for midlets persistently to store data and later retrieve those data
Comment A midlet is an MIDP application Choice denes an API for a selection of user interface components from predened number of choices This interface is used by applications that need to receive high-level events from the implementation This interface is used by applications that need to receive events that indicate changes in the internal state of the interactive items within a Form screen An alert is a screen that shows data to the user and waits for a certain period of time before proceeding to the next screen The AlertType provides an indication of the nature of an alert The Canvas class is a base class for writing applications that need to handle low-level events and to issue graphics calls for drawing to the display A ChoiceGroup is a group of selectable elements intended to be placed within a Form The Command class is a construct that encapsulates the semantic information of an action A DateField is an editable component for presenting date and time (calendar) information that may be placed into a Form Display represents the manager of the display and input devices of the system This is an object that has the capability of being placed on the display The Font class represents fonts and font metrics A Form is a Screen that contains an arbitrary mixture of items: images, read-only text elds, editable text elds, editable date elds, gauges, and choice groups The Gauge class implements a bar chart display of a value intended for use in a form Provides simple two-dimensional geometric rendering capability The Image class is used to hold graphical image data This is a class that provides layout control when Image objects are added to Form or to Alert A superclass for components that can be added to a Form and Alert The List class is a Screen containing a list of choices The common superclass of all high-level user interface classes An item that can contain a string The TextBox class is a Screen that allows the user to enter and edit text A TextField is an editable text component that may be placed into a Form Implements a ticker-tape, a piece of text that runs continuously across the display
javax.microedition.lcdui.CommandListener javax.microedition.lcdui.ItemStateListener
javax.microedition.lcdui.Gauge javax.microedition.lcdui.Graphics javax.microedition.lcdui.Image javax.microedition.lcdui.ImageItem javax.microedition.lcdui.Item javax.microedition.lcdui.List javax.microedition.lcdui.Screen javax.microedition.lcdui.StringItem javax.microedition.lcdui.TextBox javax.microedition.lcdui.TextField javax.microedition.lcdui.Ticker
Note: API, application programming interface; MIDP, mobile information device prole.
User interface classes Classes listed in Table 19.14 describe the UI and midlet application frameworks of the MIDP. Persistent data storage classes The MIDP describes a framework for storing persistent data to the nonvolatile memory of the device. The corresponding classes are described in Table 19.15. Midlets in the same midlet suite can access the data stores of each other.
MOBILE INFORMATION DEVICE PROFILE Table 19.15 Data storage classes Class javax.microedition.rms.RecordComparator Comment
441
javax.microedition.rms.RecordEnumeration javax.microedition.rms.RecordFilter
javax.microedition.rms.RecordListener
javax.microedition.rms.RecordStore
An interface dening a comparator that compares two records (in an implementation-dened manner) to see if they match or to determine their relative sort order A class representing a bidirectional record store Record enumerator An interface dening a lter that examines a record to see whether it matches (based on an application-dened criteria) A listener interface for receiving Record Changed, Added, or Deleted events from a record store A class representing a record store
Network classes and exception classes The MIDP provides the HTTP connection to the Network connection framework of the CLDC. Network and exception classes are listed in Table 19.16.
Table 19.16 (a) Network classes and (b) exception classes Class (a) Network classes javax.microedition.io.HttpConnection Comment
This interface denes the necessary methods and constants for a hypertext transfer protocol (HTTP) connection Signals that a requested midlet state change failed
19.3.3 Midlets
The application model supported in the MIDP is the midlet. A midlet runs with related applications in a midlet suite. A suite supports application interaction and data sharing to save memory. A MIDP application is a class derived from the midlet class. As an introduction to midlet programming, look at the following example:
package s60.j2me; import javax.microedition.midlet.*; import javax.microedition.lcdui.*; public class HelloWorld extends midlet implements CommandListener {
442
Command iCmdExit; TextBox iText; public HelloWorld() { iCmdExit = new Command("Exit", Command.EXIT, 1); iText = new TextBox("Midlet says:", "Hello World!", 20, TextField.ANY); iText.addCommand(iCmdExit); iText.setCommandListener(this); } protected void startApp() { Display.getDisplay(this).setCurrent(iText); } protected void pauseApp() { // empty } protected void destroyApp(boolean aIsUnconditional) { // empty } public void commandAction(Command aCmd, Displayable aDisp) { if(aCmd == iCmdExit) { destroyApp(false); notifyDestroyed(); } } }
The HelloWorld midlet is a simple application including only one class, derived from the midlet class. This enables the midlet to be run in a midlet environment. The HelloWorld midlet also implements the CommandListener interface to get events from the exit command. The HelloWorld midlet denes two member elds that store UI components: iCmdExit stores a reference to the exit command, and iText stores a reference to the Hello World text object. The constructor of the HelloWorld midlet creates the text box object and the exit command. The constructor also adds the exit command to the UI framework and adds itself to an event listener for the exit command. The Java application manager calls the startApp() method when the midlet is made visible. The startApp() method of the HelloWorld midlet simply sets the iText object to the current visible object. The pauseApp() method is called when the midlet needs to release all unnecessary resources. The HelloWorld midlet simply has nothing to release. The application manager calls the destroyApp() method before the application will be destroyed. The midlet should save its state, but the HelloWorld midlet has nothing to save. Finally, the commandAction() method implements the CommandListener interface. The application manager calls this method when the user activates the exit command of this midlet. The commandAction()
443
method simply calls the notifyDestroyed() method to notify the application manager that the midlet can now be destroyed. Because the close of the midlet was initiated by the midlet it self the application manager does not call the destroyApp() method, so the destroyApp() method is called before the notifyDestroyed() method is called.
Midlet Lifecycle
A Midlet takes several states during its lifecycle, with well-dened transitions (see Figure 19.4). It is always in one of the three states: paused, active, or destroyed. The state are listed in Table 19.17.
startApp() resumeRequest() Paused Active
Table 19.17 Midlet states State Paused Comment The midlet must release shared resources and become quiescent; can still receive asynchronous notications The midlet may hold all necessary resources for execution The midlet must release all resources and save any persistent data: cannot re-enter any other state
Started Destroyed
The transition between states can be triggered from the midlet itself or externally from the Java application manager (JAM). The application manager is the host OS application that provides tools for the end-user of the device to manage the application installed in the device. At a minimum, the JAM enables the end-user to browse, install, and
444
remove applications to the device. The JAM is described in more detail in Chapter 20. The application manager calls startApp, pauseApp, or destroyApp to notify the midlet about a state change. From inside the midlet, the resumeRequest, notifyPaused, and notifyDestroyed methods notify the application manager about a state change request. If the constructor of the midlet throws an exception, then the midlet is directly changed into the destroyed state. State changes from the JAM are as follows: startApp() is called form the application manager when the midlet is placed into the start state. This can happen at startup of the midlet or when re-entering the state after a pause. If an exception occurs, the midlet can throw MIDletStateChangeException for transient failures, otherwise it should call the destroyApp() method to cleanup. pauseApp() is called from the application manager when the system requires suspending or pausing the midlets on the device, typically when the device runs into a low-memory situation. destroyApp() is called from the application manager when the system requires terminating the midlet. The methods boolean parameter indicates whether the shutdown is unconditional. If the value is true, it means the shutdown is unconditional and the midlet has no choice but to free all resources. Otherwise, the midlet may request to stay alive by throwing a MIDletStateChangeException. It is still in the control of the application manager to accept the request. State changes from within midlet are as follows: resumeRequest() indicates to the application manager that a paused application requests to re-enter the start state to perform some processing. This is typically called after some timer events. notifyPaused() signals the application manager that the application wants to enter the pause state at its own request. Typically, the application has set up a timer and waits. notifyDestroyed() signals the application manager that the application is ready to shutdown. This time, all shared and persistent data should already be stored, because the destroyApp() method will not be called.
445
into a suite. The suites consist of a Java archive (JAR) le and a Java application descriptor (JAD) le. The JAR le contains the packed midlets and additional resources, such as images or text les, whereas the JAD le contains the midlet suite advertising information.
Application Manager
The application manager is responsible for retrieving, installing, launching, removing, and upgrading the midlet suites on the device (Figure 19.5). Single midlets are not handled by the application manager, only the suites. The MIDP specication denes only the minimum operations, and the implementation of the application manager is device-manufacture-dependent. The retrieval of midlets consists of several steps. First, the medium identication step allows the user to select the transport medium. Typical mediums are serial cable, infrared, or a type of wireless network. The second step is the negotiation step, where the midlet is advertised to the user and the device. A device may not be capable of installing the midlets because of insufcient memory. After the information is veried and the user accepts, the retrieval step starts and the actual midlet is downloaded to the device.
Discovery Midlet suite list install notify x.jad X Execution Update Midlet Server
X,Y
Xv2
Installing the suite is the next phase, and it starts with verication that the midlet does not violate any device security policies. After this has been veried, the midlet can be transformed into the devicespecic representation, which is, for example, storing the midlet into the persistent memory. After the application manager has successfully installed the midlet suite, it will notify the midlet server. This will give the application
446
provider the possibility of knowing when the midlet suite is successfully delivered to the user. This information can be used as a basis for application billing. Now the midlet is ready to be launched. Through an inspection step the user is presented with a list of available midlets. The user can now select a midlet, and the application manager launches the selected midlet. To upgrade an existing midlet the application manager keeps track of the installed midlets and their version through the identication and version management step. The older version can now be upgraded to a newer version of the suite. Removing an existing midlet suite consists of inspection of the steps and deletion. The suite and all related resources, including the persistent data, are removed from the device by this operation.
SUMMARY Table 19.18 Java application description attributes: (a) mandatory and (b) optional attributes Attribute (a) Mandatory attributes MIDlet-Name MIDlet-Version MIDlet-Vendor MIDlet-<1. . .n> MicroEdition-Prole MicroEdition-Conguration Description
447
The name of the midlet suite that identies the midlets to the user The version number of the midlet suite The organization that provides the midlet suite The name, icon, and class of the nth midlet in the Java archive le separated by a comma The Java 2 Micro Edition prole required, using the same format and value as the System property microedition.proles (e.g. MIDP-1.0) The Java 2 Micro Edition conguration required using the same format and value as the system property microedition.conguration (e.g. CLDC-1.0) The name of a PNG (portable networks graphics) le within the Java archive le used to represent the midlet suite The description of the midlet suite An URL for information further describing the midlet suite The URL from which the Java archive le can be loaded The number of bytes in the Java archive le The minimum number of bytes of persistent data required by the midlet; the default value is zero
The above JAD le denes two midlets MyMidlet1 and MyMidlet2 in the midlet suite MyMidletSuite.
19.4
Summary
Java 2 Micro Edition and MIDP provide application programmers with an easy platform to develop and distribute applications to smartphones. J2ME MIDP is targeted at mobile phones and other similar devices. It
448
provides sufciently good security and distribution models for device manufacturer to allow third parties for provide applications for a large number of handsets. For application programmers, J2ME provides a well-specied and portable environment that allows the developed applications to run in many different devices. In the next chapter we introduce the creation of Java applications for the Series 60 Platform with MIDP and present in detail the available methods and their use.
20
Midlet User Interface Framework
In this chapter we look at the midlet user interface (UI) framework. All views and items supported by the Series 60 Platform mobile information device prole (MIDP) are covered. Nokia UI application programming interface (API) classes are explained within this chapter (Section 20.2). These classes are the extension classes for default MIDP UI classes. The UI API contains also support for sound. We also show how networked midlets can be implemented. Like most things in the MIDP, networking is made as easy as possible. Currently, the Series 60 Platform supports only HTTP (hypertext transfer protocol) connections. Thus, it is not possible to use, for example, sockets. At the end of this chapter, we provide an explanation over-the-air (OTA) provisioning the way in which midlet suites can be distributed to end-users.
20.1
450
framework, as described in the previous chapter (Section 19.3). It must be safe to download and install any available midlet. The concept that the MIDP expert group introduces is based on displays. A Display class is the manager of the screen and the input devices of the system. Display is capable of showing and switching between Displayables, as shown in Figure 20.1.
Display Displayable
Screen
Canvas
List
TextBox
Alert
Form
Item
ChoiceGroup
DateField
Gauge
ImageItem
StringItem
TextField
Figure 20.1 Classes in the user interface of the mobile information device prole
Displayable is an abstract class, which may also have commands and listeners. Commands are used to retrieve user actions such as pressing a button on the command button array (CBA). Listener must be set to Displayable to retrieve these commands. There are two main categories of Displayables the abstract Canvas and the Screen class. The Canvas class is able to handle graphics and low-level events, such as the user having pressed a button. Screen is a high-level base class for the UI classes, with additional support for a ticker and title. The ticker is a piece of text that runs across the screen. Concrete Screen classes are Alert, List, TextBox, and Form. The Alert class shows the date to the user and waits a certain period of time to proceed to the next screen. List contains the list of choices. TextBox is an editable text screen. Form is the container for Items.
451
An abstract Item is a labeled component that can be added to Form. The concrete Items are ChoiceGroup, DateField, Gauge, ImageItem, StringItem, and TextField. ChoiceGroup contains selectable elements. DateField represents a time and/or date editor. Gauge represents a barchart display of a value. ImageItem is a container for Image. StringItem represents text that cannot be modied by the user. TextField is an editable representation of a string.
20.1.1
Example Application
Examples in this chapter are taken from the simple example midlet called Time Tracker. The main idea of this application is to track how long it takes to complete some tasks or projects. This application is useful, for example, for people who work on many different projects and need to estimate the time they spend on those projects per day. Example pictures can be found in later subsections. The Time Tracker user interface contains three main UI classes: List, Form, and FullCanvas. These classes are basic views that are commonly used, except that Canvas might be more useful than FullCanvas in some cases. The TTMIDlet class is used only as a startpoint in the application. It is derived from the MIDlet class. TTProjectList is the current displayable after overwritten startApp () method is called. TTProjectList is derived from the List class and it is the container of all TTProject classes. TTProjectList also shows all projects in a list on the screen. TTProject is not a UI class; it is only a container for project information such as name, description, and time used. TTProjectForm is extended from the Form class. It shows information about the project. This information is shown with different types of Items. TTProjectCanvas is derived from the FullCanvas class. It is used to show the currently used time in the specied project. Figure 20.2 shows a rough design of the Time Tracker application.
20.1.2 Display
Display represents the manager of the display and input devices of the system. It is capable of showing one Displayable object on the screen and of changing it, when needed. All Displayable objects are responsible for drawing their own context and for handling user actions. Each midlet has exactly one instance of Display. The application can get the current Display object with the getDisplay()
452
Form
CommandListener
List
MIDlet
TTProjectCanvas
TTProjectForm
TTProjectsList
TTMIDlet
0...n TTProject
Figure 20.2 Time Tracker design Table 20.1 Methods of the Display class Method Displayable getCurrent() static Display getDisplay(MIDlet m) boolean isColor() int numColors() Comment Gets the current Displayable object for this midlet Gets the Display object that is unique to this midlet Gets information about the color support of the device Gets the number of colors [if isColor() is true] or gray levels [if isColor() is false] that can be represented on the device Shows Alert and makes the transition to the next Displayable Makes the transition to the next Displayable Causes the Runnable object to call its run() method, serialized with the event stream, soon after completion of the repaint cycle
void setCurrent(Alert alert, Displayable nextDisplayable) void setCurrent(Displayable nextDisplayable) void callSerially(Runnable r)
method. The Display for that application will not change during the application lifetime. Methods of the Display class are shown in Table 20.1. In the Time Tracker example, application of the Display class is obtained in the TTMIDlet class, which extends the MIDlet class. The MIDlet class is the main class of MIDP applications. When applications are started, a new MIDlet object is created and its startApp() is called. In the following code, we get Display object in the constructor by using the static getDisplay() method of Display. The only way to change the current Displayable is done with the setCurrent() method of Displayable. Therefore, the Display object must be delivered to all objects if the current Displayable is to be changed. In startApp() method, we create TTProjectList object and give a Display to it. So, it can change the current Displayable when needed.
453
In the construction of the midlet, the Display does not have any Displayable set. It must be set with setDisplayable(), as in the startApp() method. After that, the new TTProjectList Displayable is shown in the screen:
public class TTMIDlet extends MIDlet { private Display iDisplay; // The display for this MIDlet public TTMIDlet() { iDisplay = Display.getDisplay( this ); } public void startApp() { TTProjectsList iProjectsList = new TTProjectsList( this, iDisplay ); // Switching to the TTProjectList view. iDisplay.setCurrent( iProjectsList ); } . . . }
20.1.3 Displayable
The Displayable is an object that has the capability of being placed on the display. A Displayable object may have commands and listeners associated with it. The Displayable content shown on the screen is dened in subclasses derived from Displayable. In the MIDP, there are two implemented Displayables: Canvas and Screen. Table 20.2 contains the methods of the Displayable class.
Table 20.2 Methods of the Displayable class Method void addCommand(Command cmd) boolean isShown() void removeCommand(Command cmd) void setCommandListener(CommandListener l) Comment Adds a command to the Displayable Checks if Displayable is actually visible on the display Removes a command from Displayable Sets a listener for Commands to this Displayable, replacing any previous CommandListener
In the Time Tracker example, we extend the functionality of List. List extends Displayable. There is added a new command for the second CBA button. The place of the command comes with the parameter Command.BACK. The command has now the label Exit, and that is displayed in the bottom right-hand corner of the screen. The command is added to Displayable with the addCommand()
454
method. A more complete description of the Commands is in the given in Section 20.1.4. Below, we give an example of CommandListener usage. CommandListener is an interface that can be added to the Displayable object by the setCommandListener() method. When the CommandListener is set, it retrieves high-level user actions. CommandListener must implement one method:
public void commandAction(Command c, Displayable s)
The Command parameter is used to nd out the wanted action (see Section 20.1.4 for further information). The Displayable parameter is the Displayable object, where the command occurred. There is no rule that CommandListener should be in the same class in which the actual commands exists but, at least in smaller applications, it is convenient to handle commands with views. In the Time Tracker example, we implemented CommandListener in the same class:
public class TTProjectsList extends List implements CommandListener { private static final String EXIT_LABEL = "Exit"; private Command iExitCommand; . . . public TTProjectsList( MIDlet aMIDlet, Display aDisplay ) { . . . // Creating new command with exit label, positioning it // to the second cba button with priority 1 iExitCommand = new Command( EXIT_LABEL, Command.BACK, 1 ); addCommand( iExitCommand ); // Adding itself as a CommandListener setCommandListener( this ); . . . } public void commandAction(Command c, Displayable s) { . . . } . . . }
20.1.4 Commands
The Command class provides a mechanism for user-controlled input. Displayable and almost all the derived classes support this mechanism through the addCommand() method.
455
Different implementations of MIDP may present Commands in a different way, and the device can map commands with their native style. In the Series 60 Platform, commands can be executed within Displayables by means of two softkeys in the lower display area. A single command is mapped to a Button, whereas grouped commands are mapped to menus. Commands support the concept of types and priorities. A type can be Back, Cancel, Exit, Help, Ok, Stop, Item, or Screen. The device uses the type information to place the command to the preferred place. Command types are listed in Table 20.3.
Table 20.3 Command types Method Back Cancel Exit Help Item Ok Screen Stop Comment Used to return to previous view Cancels the current action Exits the application User can request for help Command is associated with Item Positive answer Command is associated with Screen Will stop some current operation
Priority information is used to describe the importance of the command. Priorities are integer values, where a lower number indicates greater importance. Highest importance is one indicated by a value of, the second most important with a value of two, and so on. Typically, a device sorts commands rst by type and then by priority. It is not an error if commands exist with the same type and priority. In that case, device implementation will choose the order of those commands. The command constructor takes three parameters:
Command(String label, int commandType, int priority)
The label is the text that is shown to the user to represent the command. The device may override the chosen label and replace it by a more appropriate label for this command on the device. The command methods are described in Table 20.4.
Table 20.4 Methods of the Command class Method int getCommandType() String getLabel() Int getPriority() Comment Gets the type of the command Gets the label of the command Gets the priority of the command
456
Third, set the listener to the displayable; the object needs to implement the CommandListener interface:
setCommandListener(this);
20.1.5 Canvas
The Canvas class extends the Displayable class. Canvas is used in applications that need to control drawing to the display and retrieve low-level user inputs. It can be shown with the setCurrent() method of Display and acts like other Displayables. Canvas is an abstract class, so it must be extended before it can be used. The paint method must be overridden in order to perform custom graphics on the canvas. The paint method argument is a Graphics object. The Graphics class has standard primitive drawing methods to draw on-screen. By overwriting the keyPressed(), keyReleased(), and/or keyRepeated() methods, key events can be captured. This is very useful, for instance, when developing games or other applications that need many instant user actions. The key codes are delivered in the method, and the most common keys can be found as constants in the Canvas class. The Canvas class provides access for pointer events, but there is no pointer in the Series 60 and therefore these are useless. The Canvas class is notied for showing and hiding through the showNotify() and hideNotify() methods. By overwriting those methods, notication can be fetched. All methods of the Canvas class
DEFINING THE MIDLET USER INTERFACE Table 20.5 Methods of the Canvas class Method int getHeight() int getKeyCode(int gameAction) String getKeyName(int keyCode) int getWidth() boolean hasPointerEvents() boolean hasPointerMotionEvents() boolean hasRepeatEvents() protected void hideNotify() boolean isDoubleBuffered() protected void keyPressed(int keyCode) protected void keyReleased(int keyCode) protected void keyRepeated(int keyCode) protected abstract void paint(Graphics g) protected void pointerDragged(int x, int y) protected void pointerPressed(int x, int y) protected void pointerReleased(int x, int y) void repaint() void repaint(int x, int y, int width, int height) void serviceRepaints() protected void showNotify() Comment
457
Gets height of the displayable area, in pixels Gets a key code that corresponds to the specied game action on the device Gets an informative key string for a key Gets width of the displayable area, in pixels Checks if the platform supports pointer press and release events Checks if the platform supports pointer motion events (pointer dragged) Checks if the platform can generate repeat events when key is kept down The implementation calls hideNotify() shortly after Canvas has been removed from the display Checks if Graphics is double-buffered by the implementation Called when a key is pressed Called when a key is released Called when a key is repeated (held down) Renders Canvas Called when the pointer is dragged Called when the pointer is pressed Called when the pointer is released Requests a repaint for the entire Canvas Requests a repaint for the specied region of the Screen Forces any pending repaint requests to be serviced immediately The implementation calls showNotify() immediately prior to this Canvas being made visible on the display Gets the game action associated with the given key code of the device Gets height of the displayable area, in pixels
are described in Table 20.5. An example of Canvas usage can be found in Section 20.2.2, in the subsection on FullCanvas.
20.1.6 Screen
The Screen class is a displayable object that can be set to current and displayed in the display. It extends the functionality of Displayable
458
with support for the title and ticker. Screen is an abstract class and must be extended to offer custom functionality. Instantiable subclasses of Screen are Alert, Form, List, and TextBox. In the Time Tracker example, we have used many Screens. The Form screen is used to display project information and to allow the user to edit it. The Alert class is used to inform the user of errors and other events, and the user can select one project from the List object. Each Screen object is described more precisely in other sections of this chapter. The methods of the Screen class are described in Table 20.6.
Table 20.6 Methods of the Screen class Method String getTitle() void setTicker(Ticker ticker) void setTitle(String s) Ticker getTicker() Comment Gets the title of Screen Sets a ticker for use with this Screen, replacing any previous ticker Sets the title of Screen Gets the ticker used by this Screen
20.1.7 Graphics
The Graphics class provides simple drawing methods and control for color, translation, and clipping. The basic drawing shapes are arcs, lines, and rectangles, as shown in Figure 20.3. It is also possible to draw images and strings.
Graphics can be used with Canvas and Image. With the Canvas object, Graphics is delivered with the paint() method. The Graphics object can be used to draw to an off-screen image. The Graphics object from Image can be obtained with the getGraphics() method. The methods of the Graphics class are described in Table 20.7.
DEFINING THE MIDLET USER INTERFACE Table 20.7 Methods of the Graphics class Method void clipRect(int x, int y, int width, int height) void drawArc(int x, int y, int width, int height, int startAngle, int arcAngle) void drawChar(char character, int x, int y, int anchor) void drawChars(char[] data, int offset, int length, int x, int y, int anchor) void drawImage(Image img, int x, int y, int anchor) void drawLine(int x1, int y1, int x2, int y2) void drawRect(int x, int y, int width, int height) void drawRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight) void drawString(String str, int x, int y, int anchor) void drawSubstring(String str, int offset, int len, int x, int y, int anchor) void fillArc(int x, int y, int width, int height, int startAngle, int arcAngle) void fillRect(int x, int y, int width, int height) void fillRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight) int getBlueComponent() int getClipHeight() int getClipWidth() int getClipX() Comment
459
Intersects the current clip with the specied rectangle Draws the outline of a circular or elliptical arc covering the specied rectangle, using the current color and stroke style Draws the specied character using the current font and color Draws the specied characters using the current font and color Draws the specied image by using the anchor point Draws a line between the coordinates (x1,y1) and (x2,y2) using the current color and stroke style Draws the outline of the specied rectangle using the current color and stroke style Draws the outline of the specied rounded corner rectangle using the current color and stroke style Draws the specied String using the current font and color Draws the specied String using the current font and color Fills a circular or elliptical arc covering the specied rectangle Fills the specied rectangle with the current color Fills the specied rounded corner rectangle with the current color Gets the blue component of the current color Gets the height of the current clipping area Gets the width of the current clipping area Gets the X offset of the current clipping area, relative to the coordinate system origin of this graphics context Gets the Y offset of the current clipping area, relative to the coordinate system origin of this graphics context Gets the current color Gets the current font Gets the current gray-scale value of the color being used for rendering operations Gets the green component of the current color Gets the red component of the current color (continued overleaf )
int getClipY()
int getColor() Font getFont() int getGrayScale() int getGreenComponent() int getRedComponent()
460 Table 20.7 (continued ) Method int getStrokeStyle() int getTranslateX() int getTranslateY()
Comment Gets the stroke style used for drawing operations Gets the X coordinate of the translated origin of this graphics context Gets the Y coordinate of the translated origin of this graphics context Sets the current clip to the rectangle specied by the given coordinates Sets the current color to the specied RGB (redgreenblue) values Sets the current color to the specied RGB values Sets the font for all subsequent text rendering operations Sets the current gray scale to be used for all subsequent rendering operations Sets the stroke style used for drawing lines, arcs, rectangles, and rounded rectangles Translates the origin of the graphics context to the point (x , y ) in the current coordinate system
void setClip(int x, int y, int width, int height) void setColor(int RGB) void setColor(int red, int green, int blue) void setFont(Font font) void setGrayScale(int value) void setStrokeStyle(int style) void translate(int x, int y)
Strings can be drawn with specied font and color, and there is a special method for drawing substrings, (see Section 20.1.14 for further information on Font usage). Characters and character arrays can be also drawn without converting these to Strings.
20.1.8 Form
The Form class is a graphical container for Item objects. Items can be appended on, added to, or inserted in the Form, or removed from it. Item objects are controlled within the Form by their index numbers. Same instance of Item can be only in a one Form. If the application attempts to append Item, which is already appended to some Form, IllegalStateException is thrown. Items are placed in Form, one upon the other. Form takes care of the layout of the Items and scrolls all Items when needed. The Item objects may not have their own scrolling functionality. Methods of the Form class are described in Table 20.8. In the Time Tracker example, we have extended Form and added some Items to it, as shown in Figure 20.4. TTProjectForm is used to view and edit project information. Each project has a name, duration, and description. These properties are presented with Items, which are added to the Form by the append method, in the setupFormFields() method.
DEFINING THE MIDLET USER INTERFACE Table 20.8 Methods of the Form class Method int append(Image img) int append(Item item) int append(String str) void delete(int itemNum) Item get(int itemNum) void insert(int itemNum, Item item) void set(int itemNum, Item item) Void setItemStateListener(ItemStateListener iListener) int size() Comment
461
Adds an item consisting of one Image to the form Adds an item into Form Adds an item consisting of one String into the form Deletes the Item referenced by itemNum Gets the item at a given position Inserts an item into the Form just before the item specied Sets the item referenced by itemNum to the specied Item, replacing the previous item Sets the ItemStateListener for the Form, replacing any previous ItemStateListener Gets the number of items in Form
Figure 20.4 Form in Time Tracker with TextField, StringItem, DateField, and Gauge
We added TextField, StringItem, DateField, and Gauge items to Form. TextField is used to edit the project title. StringItem represents the project description, which cannot be modied in this view. DateField is used to show the current duration of the project. The Gauge object shows what percentage of time this project has taken compared with other projects. It is constructed with a maximum value of 100, and the initial value is zero. The value of the Gauge object is changed with the setValue() method, when a new project is set to this Form.
462
TTProjectForm implements ItemStateListener, which can be used to observe when the Items state changes. The ItemStateListener must be set to Form with the setItemStateListener() method to make it function, which is done in this example by the setupFormFields() method:
public class TTProjectForm extends Form implements CommandListener, ItemStateListener { . . . private TTProjectsList iProjectsList; private TTProject iProject; // Project name TextField private static final String PROJECT_NAME = "Project name"; private static final int PROJECT_NAME_MAX_LENGTH = 20; private TextField iNameItem = new TextField( PROJECT_NAME, "", PROJECT_NAME_MAX_LENGTH, TextField.ANY ); // Project description StringItem private static final String PROJECT_DESC = "Project description"; private StringItem iDescItem = new StringItem( PROJECT_DESC, "" ); //Project current duration private static final String PROJECT_TIME = "Project curr. duration"; private DateField iTimeItem = new DateField( PROJECT_TIME, DateField.TIME ); //Project duration percents in all projects private static final String PROJECT_TIME_PERCENTS = "Project curr. dur. %"; private Gauge iPercentGauge = new Gauge( PROJECT_TIME_PERCENTS, false, 100, 0); public void setProject( TTProject aProject ) { iProject = aProject; // Setting form header to projects name setTitle( aProject.getName() ); // Setting project name to the TextField also iNameItem.setString( aProject.getName() ); // Setting project description to the StringItem iDescItem.setText( aProject.getDescription() ); // Setting used time to the DateField iTimeItem.setDate( aProject.getTime() ); // Setting all percents to the Gauge iPercentGauge.setValue( (int)( (aProject.getTimeInMillis()*100) /
DEFINING THE MIDLET USER INTERFACE iProjectsList.getProjectsDuration() ) ); } private void setupFormFields() { append( iNameItem ); setItemStateListener( this ); append( iDescItem ); append( iTimeItem ); append( iPercentGauge ); } . . . public void itemStateChanged( Item item ) { . . . } . . . }
463
20.1.9 Image
The Image class is used to contain graphical image data. The Image objects do not depend on the display of the device and will not be drawn unless they are especially told to. Images can be created from the data array, from another Image, or from image les. Images can be categorized into two groups: mutable and immutable. An immutable Image cannot be modied after it is created. Methods of the Image class are described in Table 20.9. An example for creating Image from the byte array can be found in Section 20.3.
Table 20.9 Methods of the Image class Method static Image createImage(byte[] imageData, int imageOffset, int imageLength) static Image createImage(Image source) static Image createImage(int width, int height) static Image createImage(String name) Graphics getGraphics() int getHeight() int getWidth() Boolean isMutable() Comment Creates an immutable image that is decoded from the data stored in the specied byte array at the specied offset and length. Creates an immutable image from a source image Creates a new, mutable image for off-screen drawing Creates an immutable image from decoded image data obtained from the named resource Creates a new Graphics object that renders to this image Gets the height of the image in pixels Gets the width of the image in pixels Checks if this image is mutable
464
20.1.10 Ticker
The Ticker class provides scrolling text across the display. The direction and speed of the scrolling are determined by the implementation. In the Series 60 Platform the text scrolls from right to left in the upper part of the display, as shown in Figure 20.5.
A Ticker object can be used with Screen objects. Ticker is set to the Screen object with the setTicker() method, and it is shown when Screen is displayed. The same Ticker object can be set to several Screen objects. A typical use is for an application to place the same ticker on all of its screens. When the application switches between two screens that have the same ticker, a desirable effect 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 to each screen. The methods of the Ticker class are shown in Table 20.10.
Table 20.10 Methods of the Screen class Method String getString() void setString(String str) Comment Gets the string currently being scrolled by the ticker Sets the string to be displayed by this ticker
While animating, the ticker string scrolls continuously. That is, when the string nishes scrolling off the display, the ticker starts over at the beginning of the string. The following Screen method can show Ticker:
iScreen.setTicker( new Ticker( "scrolling text" ) );
20.1.11 TextBox
The TextBox class is a Screen for text editing and text insertion. It can have constraints to restrict the users input capabilities. The input constraints are dened in the TextField class. (see Section 20.1.20 for further information on constraints). TextBox constructor is as follows:
TextBox(String title, String text, int maxSize, int constraints)
465
The title is the text shown in the Screen title. The text parameter is the text placed initially in the TextBox before the user or the application edits the contents. The maxSize parameter denes the maximum number of characters that can be stored to TextBox. The maximum must be dened, and the implementation may also need to downscale the capacity. The real capacity of TextBox can be obtained with the getMaxSize() method. Applications should check the capacity with this method and not exceed the capacity. After construction, the maximum size of the TextBox can be changed by the setMaxSize() method. If the current number of characters in the TextBox is too great, the contents will be truncated to t to the new size. The method returns the new size of the TextBox. The size can be smaller than the requested size. The maximum size is not the number of characters that is shown in the screen. If the TextBox has more characters that can be shown on the screen at the same time, the TextBox will allow the user to scroll the text and edit it at the selected point. The content of TextBox can be modied and obtained by several methods. The application can obtain the context of TextBox with the getChars() or getString() methods. The method getChars() copies the context of TextBox into a character array, and the method getString() returns the String object containing the context. There are also similar methods for setting the context and partially modifying the context. Table 20.11 contains the methods of the TextBox class.
20.1.12 Choice
Choice is an interface for the UI classes that implement selection from a predened number of choices. The methods of Choice are listed in Table 20.12. In MIDP, there are two implemented Choice classes: List and ChoiceGroup. The use of both classes is basically the same. There are only a few differences, such as supported selection modes.
ChoiceGroup
ChoiceGroup is an implementation of Choice and extends the Item class. Therefore, ChoiceGroup is used within the Form class. ChoiceGroup only supports exclusive-choice (shown in Figure 20.6) and multiple-choice types. The implementation must provide a different graphical presentation for each mode. The exclusive mode might be represented, for example, with radio buttons, and multiple modes with check boxes.
466
Table 20.11 Methods of the TextBox class Method void delete(int offset, int length) int getCaretPosition() int getChars(char[] data) int getConstraints() int getMaxSize() String getString() void insert(char[] data, int offset, int length, int position) void insert(String src, int position) void setChars(char[] data, int offset, int length) void setConstraints(int constraints) int setMaxSize(int maxSize) void setString(String text) int size() Comment Deletes characters from TextBox Gets the current input position Copies the contents of TextBox into a character array, starting at index zero Gets the current input constraints of TextBox Returns the maximum size (number of characters) that can be stored in this TextBox Gets the contents of TextBox as a string value Inserts a subrange of an array of characters into the contents of TextBox Inserts a string into the contents of TextBox Sets the contents of TextBox from a character array, replacing the previous contents Sets the input constraints of TextBox Sets the maximum size (number of characters) that can be contained in this TextBox Sets the contents of TextBox as a string value, replacing the previous contents Gets the number of characters that are currently stored in this TextBox
The String parameter label is text shown in the Item label. The Choice type cannot be implicit, but all the other choice types dened in Choice can. The group can be constructed with the String element array. Each element in the array forms one choice. The Image array is optional. If the image element array is not null, the length of the array must be at least the number of string elements. The state of ChoiceGroup can be observed with ItemStateListener. The listener is called every time the user changes the selections in choice group. When the listener is called the choice group can be
467
Table 20.12 Methods of the Choice interface Method String getString(int elementNum) Image getImage(int elementNum) int append(String stringPart, Image imagePart) void insert(int elementNum, String stringPart, Image imagePart) void delete(int elementNum) void set(int elementNum, String stringPart, Image imagePart) boolean isSelected(int elementNum) int getSelectedIndex() int getSelectedFlags(boolean[] selectedArray_return) void setSelectedIndex(int elementNum, boolean selected) void setSelectedFlags(boolean[] selectedArray) int size() Comment Gets the String part of the element referenced by elementNum Gets the Image part of the element referenced by elementNum Appends an element to Choice Inserts an element into Choice just prior to the element specied Deletes the element referenced by elementNum Sets the element referenced by elementNum to the specied element, replacing the previous contents of the element Gets a boolean value indicating whether this element is selected Returns the index number of an element in Choice that is selected Queries the state of a Choice and returns the state of all elements in the boolean array selectedArray_return For MULTIPLE, this simply sets an individual elements selected state Attempts to set the selected state of every element in Choice Gets the number of elements present
468
queried for selected elements. ItemStateListener must implement only one method:
public void itemStateChanged( Item item )
A parameter item is the choice group where the event occurred. To get events, the listener must be added to Form.
List
The List class is a Screen that provides a list of choices, as shown in Figure 20.7. As List extends Screen, it can have a ticker and contain commands. List supports all selection modes dened in Choice.
The list can be observed for changes only in the implicit selection mode. It can be observed with registered CommandListener. The list has a special select Command, which will be delivered to CommandListeners when the state of the list changes:
public class TTProjectsList extends List implements CommandListener { static private final String LIST_NAME = "Time Tracker"; private Vector iProjects = new Vector(); . . .
469
public void commandAction(Command c, Displayable s) { . . . else if( c == List.SELECT_COMMAND ) { // User has selected one of the projects from the list // getting which one with getSelectedIndex() iProjectForm.setProject( (TTProject)iProjects.elementAt ( getSelectedIndex()) ); . . . } } . . . }
20.1.13 Alert
The Alert class is a user interface informing the user about errors and other events: Alert extends the Screen class, but does not accept any application-dened Commands. Alert has a label and possibly an image. Alert stays activated for a certain amount of time or until the user dismisses it. The method constructs a new Alert object with a given title and content String (alertText):
public Alert(String title, String alertText, Image alertImage, AlertType alerttType)
The image is optional and the parameter can be null if no image is needed. All images in alerts must be immutable. The AlertType class is a class presenting the type of the alert. There are ve predened alert types: ALARM, CONFIRMATION, ERROR, INFO (information), and WARNING. Alert types are listed in Table 20.13. The AlertType class has a method to enable sounds in the alerts:
public boolean playSound(Display display)
470 Table 20.13 Alert types AlertType ALARM CONFIRMATION ERROR INFO WARNING
Comment An ALARM is a hint to alert the user to an event for which the user has previously requested notication. A CONFIRMATION AlertType is a hint to conrm user actions An ERROR AlertType is a hint to alert the user to erroneous operation An INFO AlertType typically provides nonthreatening information to the user A WARNING AlertType is a hint to warn the user of a potentially dangerous operation
The user is alerted when the sound for this AlertType is played. The AlertType instance is used as a hint by the device to generate an appropriate sound. Instances other than those predened above may be ignored. The implementation may determine the sound to be played. The implementation may also ignore the request, use the same sound for several AlertTypes, or use any other means suitable to alert the user. Alerts can be shown with the following Display method:
public void setCurrent(Alert alert, Displayable nextDisplayable)
This method sets the alert to the current Displayable. When the alert dismisses the nextDisplayable Displayable is set current. Display object will not wait for the alert to dismiss, and returns immediately. The next displayable must be dened and cannot be the alert object. Methods of the Alert Clas are listed in Table 20.14. There is an alert of the CONFIRMATION type, as shown in Figure 20.8.
20.1.14 Font
The Font class represents the fonts and font metrics. The applications do not create the fonts by themselves. Instead, the fonts must be queried with font attributes, and the system will attempt to provide a font that matches the requested attributes as closely as possible. Since only static system fonts are used, it eliminates the garbage creation normally associated with the use of fonts. Methods of the Font class are listed in Table 20.15. All fonts are queried with the following method:
static Font getFont(int face, int style, int size)
DEFINING THE MIDLET USER INTERFACE Table 20.14 Methods of the Alert class Method void addCommand(Command cmd) Comment
471
int getDefaultTimeout() Image getImage() String getString() int getTimeout() AlertType getType() Void setCommandListener(CommandListener l) void void void void setImage(Image img) setString(String str) setTimeout(int time) setType(AlertType type)
Commands are not allowed on an Alert, so this method will always throw IllegalStateException whenever it is called Gets the default time for showing Alert Gets the Image used in Alert Gets the text string used in Alert Gets the time this Alert will be shown Gets the type of Alert Listeners are not allowed on an Alert, so this method will always throw IllegalStateException whenever it is called Sets the Image used in Alert Sets the text string used in Alert Set the time for which Alert is to be shown Sets the type of Alert
Figure 20.8
The Fonts attributes are style, size, and face. Values for attributes must be specied in terms of symbolic constants:
Face:FACE_MONOSPACE, FACE_PROPORTIONAL, FACE_SYSTEM Style:STYLE_BOLD, STYLE_ITALIC, STYLE_PLAIN, STYLE_UNDERLINED Size:SIZE_LARGE, SIZE_MEDIUM, SIZE_SMALL
The values for the style attribute may be combined by using the logical OR operator: The following example shows how a new Font can be set to Graphics, and how its measurement methods are used:
472
Table 20.15 Methods of the Font class Method int charsWidth(char[] ch, int offset, int length) int charWidth(char ch) int getBaselinePosition() static Font getDefaultFont() int getFace() static Font getFont(int face, int style, int size) int getHeight() int getSize() int getStyle() boolean isBold() boolean isItalic() boolean isPlain() boolean isUnderlined() int stringWidth(String str) int substringWidth(String str, int offset, int len) Comment Returns the advance width of the characters in ch, starting at the specied offset and for the specied number of characters (length) Gets the advance width of the specied character in this font. Gets the distance in pixels from the top of the text to the baseline of the text Gets the default font of the system Gets the face of the font Obtains an object representing a font having the specied face, style, and size Gets the standard height of a line of text in this font Gets the size of the font Gets the style of the font Returns true if the font is bold Returns true if the font is italic Returns true if the font is plain Returns true if the font is underlined Gets the total advance width for showing the specied String in this Font Gets the total advance width for showing the specied substring in this font
public class TTProjectCanvas extends FullCanvas { . . . private static final String STOP_TXT = "Stop"; . . . public void paint( Graphics aG ) { . . . //Getting a new font Font fnt = Font.getFont(Font.FACE_PROPORTIONAL, Font.SIZE_MEDIUM, Font.STYLE_PLAIN ); //Setting it to Graphics object aG.setFont( fnt ); //Drawing stop text to exactly bottom right corner aG.drawString( STOP_TXT, getWidth()-fnt.stringWidth( STOP_TXT ), getHeight()-fnt.getHeight(), aG.TOP | aG.LEFT ); . . . } . . . }
At rst, the desired font is obtained with the getFont() method, which takes attributes describing the Font features as a parameter. The Font is set to the current Font of the Graphic object. Text stop is drawn to the bottom right-hand corner of the display. The drawing position is calculated by using Canvas size and Font dimensions.
473
20.1.15 Item
The Item class is an abstract base class for the UI components that can be added to Form. All Item objects have a label, which is a string that is attached to the Item. The label is typically displayed near the component when it is displayed within a screen. In the Series 60 Platform, the label is above the Item object and scrolls with the item. Item methods are listed in Table 20.16
Table 20.16 Methods of the Item class Method String getLabel() void setLabel(String label) Comment Gets the label of this Item object Sets the label of Item
Items must be added to a Form to make them visible. Item is shown when Form is the current Displayable and the Form focus is above the Item.
20.1.16 DateField
DateField is an editable component for presenting the calendar date and time information that may be placed into a Form. An instance of a DateField can be congured to accept the date or time information or both. Input modes and types in the DateField class are dened in Tables 20.17(a) 20.17(b), respectively. There is an example of DateField use in the Form example (Section 20.1.8).
Table 20.17 The DateField class: (a) input modes and (b) input types Comment (a) Input mode DATE TIME DATE_TIME (b) Input type Date getDate() int getInputMode() void setDate(Date date) void setInputMode(int mode)
Date information (day, month, and year) Time information (hours and minutes) Date and time information Returns date value of this eld Gets input mode for this date eld Sets a new value for this eld Set input mode for this date eld
20.1.17 Gauge
The Gauge class implements a barchart display of a value intended for use in a Form:
Gauge(String label, boolean interactive, int maxValue, int initialValue)
474
The Gauge accepts values from zero to a maximum value established by the application. The application is expected to normalize its values into this range. The device is expected to normalize this range into a smaller set of values for display purposes. In doing so, it will not change the actual value contained within the object. The range of values specied by the application may be larger than the number of distinct visual states possible on the device, so more than one value may have the same visual representation. The methods of the Cauge class are listed in Table 20.18.
Table 20.18 Methods in the Gauge class Method int getMaxValue() int getValue() boolean isInteractive() void setMaxValue(int maxValue) void setValue(int value) Comment Gets the maximum value of this Gauge object Gets the current value of this Gauge object Tells whether the user is allowed to change the value of the Gauge Sets the maximum value of this Gauge object Sets the current value of this Gauge object
There is an example of the use of Gauge in the Form example (Section 20.1.8).
20.1.18 ImageItem
ImageItem is an Item class that contains an Image and label. The label is typically shown above the image part.
ImageItem(String label, Image img, int layout, String altText)
It can be added to a Form, and then it acts like other Items. The label is typically shown above the image part. The Label parameter is the label of the Item. Parameter img is the image part of the ImageItem. If the img parameter is null, the item uses only the space needed by the label. The whole Item is not shown if there is no image and no label. The layout parameter species how the image is drawn to the screen. Some of the layout constants can be combined, such as in LAYOUT_NEWLINE_BEFORE | LAYOUT_LEFT. The default layout parameter cannot be combined with other layouts. The layout constants are listed in Table 20.19. An alternative text layout is shown if the image part cannot be shown, which may occur when the image exceeds the capacity of the display device. The methods of the ImageItem class are listed in Table 20.20.
DEFINING THE MIDLET USER INTERFACE Table 20.19 Layout constants of the ImageItem class Method LAYOUT_CENTER LAYOUT_DEFAULT LAYOUT_LEFT LAYOUT_NEWLINE_AFTER LAYOUT_NEWLINE_BEFORE LAYOUT_RIGHT Comment Image should be horizontally centered Use the default formatting of the container of the image Image should be close to the left edge of the drawing area A new line should be started after the image is drawn A new line should be started before the image is drawn Image should be close to the right edge of the drawing area
475
Table 20.20 Methods of the ImageItem class Method String getAltText() Image getImage() int getLayout() void setAltText(String text) void setImage(Image img) void setLayout(int layout) Comment Gets the text string to be used if the image exceeds the capacity of the device to display it Gets the image contained within ImageItem, or is null if there is no contained image Gets the layout directives used for placing the image Sets the alternative text of the ImageItem, or is null if no alternate text is provided Sets the image object contained within the ImageItem Sets the layout directives
20.1.19 StringItem
The StringItem class is an item that can contain a string. StringItem is display-only; the user cannot edit the contents. Both the label and the textual content of StringItem may be modied by the application. The visual representation of the label may differ from that of the textual contents. The methods of the StringItem class are listed in Table 20.21. There is an example for StringItem in the Form example (Section 20.1.8).
Table 20.21 Methods in the StringItem class Method String getText() void setText(String text) Comment Gets the text contents of StringItem, or is null if the StringItem class is empty Sets the text contents of StringItem
20.1.20 TextField
The TextField class is an Item that contains text. The user can edit the content of the TextField and the input capabilities can be restricted with constraints. The TextField constructor is as follows:
476
The label parameter is the label of the Item, which is shown above the Item. The text parameter is the initial text, which is placed in the TextField when it is shown. The maximum size parameter (max Size) is the number of characters that can be used in the TextField. The user input capabilities may be restricted by the constraints parameter. The constraints parameter is a predened constant in the TextField class. Any constraint can be used to allow the user to enter any text. Other constraints are e-mail address, number, password, and URL (universal resource locator). Methods in the TextField class are listed in Table 20.22. There is an example the use of TextField in the Form example (Section 20.1.8).
Table 20.22 Methods in the TextField class Method void delete(int offset, int length) int getCaretPosition() int getChars(char[] data) int getConstraints() int getMaxSize() String getString() void insert(char[] data, int offset, int length, int position) void insert(String src, int position) void setChars(char[] data, int offset, int length) void setConstraints(int constraints) int setMaxSize(int maxSize) void setString(String text) int size() Comment Deletes characters from TextField Gets the current input position Copies the contents of TextField into a character array, starting at index zero Gets the current input constraints of TextField Returns the maximum size (number of characters) that can be stored in this TextField Gets the contents of TextField as a string value Inserts a subrange of an array of characters into the contents of TextField Inserts a string into the contents of TextField Sets the contents of TextField from a character array, replacing the previous contents Sets the input constraints of TextField Sets the maximum size (number of characters) that can be contained in this TextField Sets the contents of TextField as a string value, replacing the previous contents Gets the number of characters that are currently stored in this TextField
477
need some low-level access to the device. The Nokia UI API provides access to the control keys and the display more efciently than can be achieved with the original MIDP classes. The main goal of this extension API is to enhance the developers capability of implementing high-quality games for Nokia devices. The main features in the Nokia UI API are as follows: low-level access to image pixel data transparency support full-screen drawing sound vibration and device light control
20.2.1
Package Overview
The Nokia UI API contains two packages user interface and sound, as shown in Table 20.23. These packages come with the Series 60 Platform MIDP as built-in, so the developer does not need to worry about compatibility between Nokia devices. However, it must be kept in mind that these classes cannot be found elsewhere.
Table 20.23 Packages in the Nokia user interface Package com.nokia.mid.ui Description Provides user interface extensions for MIDP (mobile information device prole) applications Contains a class and an interface for simple sound playback
com.nokia.mid.sound
478
The operations in DirectGraphics also affect the original graphics object, and vice versa. For instance, setting the color with DirectGraphics also affects the Graphics object, and setting a clipping rectangle to the Graphics affects DirectGraphics. Developers may consider DirectGraphics as a new way to make calls to Graphics. DirectGraphics does not inherit Graphics because of the API dependency. Some DirectGraphics methods take the color as the ARGB (alpharedgreenblue) value. This value is in the form of 0xAARRGGBB, and it corresponds to the native format specied by TYPE_ INT_8888_ARGB. An alpha value 0xFF indicates opacity, and a value of 0x00 full transparency. All drawPixels() and getPixels() methods take the format of a parameter. There are six main types that are supported in the Series 60 Platform, and these formats are listed in Table 20.24. Table 20.25 contains the list of supported methods.
Table 20.24 Supported image formats Image format TYPE_BYTE_1_GRAY TYPE_BYTE_1_GRAY_VERTICAL TYPE_USHORT_444_RGB TYPE_USHORT_4444_ARGB TYPE_INT_888_RGB TYPE_INT_8888_ARGB Comment 1 bit format, 2 distinct color values (on or off), stored as a byte 1 bit format, 2 distinct color values (on or off), stored as a byte 4 bits for red, green, and blue component in a pixel, stored as a short (0x0RGB) 4 bits for alpha, red, green, and blue component in a pixel, stored as a short (0xARGB) 8 bits for red, green, and blue component in a pixel (0x00RRGGBB) 8 bits for alpha, red, green, and blue component in a pixel (0xAARRGGBB)
Table 20.25 Methods in the DirectGraphics class Method void drawImage (javax.microedition.lcdui.Image img, int x, int y, int anchor, int manipulation) void drawPixels(byte[] pixels, byte[] transparencyMask, int offset, int scanlength, int x, int y, int width, int height, int manipulation, int format) void drawPixels(int[] pixels, boolean transparency, int offset, int scanlength, int x, int y, int width, int height, int manipulation, int format) Comment This method is almost similar to drawImage in Graphics, but it also has a manipulation facility that can be used to rotate and/or ip the image This method is used to draw raw pixel data to the graphics context to the specied location. Only the byte-based formats are used (TYPE_BYTE_1_GRAY and TYPE_BYTE_1_GRAY_VERTICAL). The transparency mask is in the same format as pixels This method is used to draw pixels in the int-based formats (TYPE_INT_888_RGB or TYPE_INT_8888_ARGB). If transparency ag is true then transparency information is used (if there is any)
NOKIA USER INTERFACE CLASSES Table 20.25 (continued ) Method void drawPixels(short[] pixels, boolean transparency, int offset, int scanlength, int x, int y, int width, int height, int manipulation, int format) void drawPolygon(int[] xPoints, int xOffset, int[] yPoints, int yOffset, int nPoints, int argbColor) void drawTriangle(int x1, int y1, int x2, int y2, int x3, int y3, int argbColor) void fillPolygon(int[] xPoints, int xOffset, int[] yPoints, int yOffset, int nPoints, int argbColor) void fillTriangle(int x1, int y1, int x2, int y2, int x3, int y3, int argbColor) int getAlphaComponent() int getNativePixelFormat() Comment
479
This method is used to draw pixels in the short-based formats (TYPE_USHORT_444_RGB or TYPE_USHORT_4444_RGB)
void getPixels(byte[] pixels, byte[] transparencyMask, int offset, int scanlength, int x, int y, int width, int height, int format) void getPixels(int[] pixels, int offset, int scanlength, int x, int y, int width, int height, int format) void getPixels(short[] pixels, int offset, int scanlength, int x, int y, int width, int height, int format) void setARGBColor(int argbColor)
Gets the alpha component of the current color Returns the native pixel format of an implementation (TYPE_USHORT_4444_ARGB in the Series 60 Platform) Copies pixels from the specied location in the graphics context to the byte array. Only the byte-based formats are used (TYPE_BYTE_1_GRAY and TYPE_BYTE_1_GRAY_VERTICAL) Copies pixels from the graphic context to the int array in the int-based format (TYPE_INT_888_RGB or TYPE_INT_8888_ARGB) Copies pixels from the graphic context to the short array in the short-based format (TYPE_USHORT_444_RGB or TYPE_USHORT_4444_RGB) Sets the current color to the specied ARGB (alpharedgreenblue) value
Combining FLIP_HORIZONTAL, FLIP_VERTICAL, ROTATE_90, ROTATE_180, or ROTATE_270 with OR operator forms manipulation parameters to drawPixels() and drawImage(). These combinations are always handled in the same order: rst the rotation, then the vertical ip, and, nally, the horizontal ip. The creation of a combination is shown later, in an example. The following example is an except from the TTProjectCanvas. It draws the background image and then a 50% transparent red polygon
480
in the middle of screen. After this, it draws the current time over that polygon.
void paint( Graphics aG ) { . . . // Getting direct graphics DirectGraphics dg = DirectUtils.getDirectGraphics( aG ); // drawing background image, no manipulation dg.drawImage( iBackGround, 0, 0, aG.TOP | aG.LEFT, 0 ); // initializing position for polygon int[] xPos = {0, getWidth(), getWidth(), 0}; int[] yPos = {getHeight() / 2 - 20, getHeight() / 2 - 20, getHeight() / 2 + 20, getHeight() / 2 + 20}; // drawing 50% transparent red polygon in the middle of // the screen dg.fillPolygon( xPos, 0, yPos, 0, xPos.length, 0x77FF0000 ); // Setting color to white aG.setColor( 255, 255, 255 ); // Getting a new font Font fnt = Font.getFont(Font.FACE_PROPORTIONAL, Font.SIZE_MEDIUM, Font.STYLE_PLAIN ); // Setting it to Graphics object aG.setFont( fnt ); // drawing current time string to the middle of the screen aG.drawString( iCurrentTimeStr, (getWidth()/2)fnt.stringWidth( iCurrentTimeStr )/2, (getHeight()/2)-(fnt.getHeight()/2), aG.TOP ); . . . }
DeviceControl
DeviceControl contains a collection of methods (listed in Table 20.26) for controlling the special features of the device, such as vibration and screen backlight. For example, ashing the backlights for 1 sec and can be done as follows:
DeviceControl.flashLights( 1000 );
DirectUtils
The DirectUtils class contains a collection of static utility methods, listed in Table 20.27. These methods are used for converting the
NOKIA USER INTERFACE CLASSES Table 20.26 Methods in the DeviceControl class Method static void flashLights(long duration) static void SetLights(int num, int level) Comment
481
Temporarily ashes the lights for a specic length of time, in milliseconds Turns lights on and off. The rst parameter indicates which lights are controlled; 0 is assigned to backlights and the rest is left unspecied. The level controls the brightness; values are between 0100 and, in most cases, 1100 indicate on, and 0 is off Activates vibration for a given length of time in milliseconds and with a frequency between 0100. A value of 0 is no vibration. If the device does not support different vibration frequencies then the device default is used Stops any vibration
Table 20.27 Methods in the DirectUtils class Method static javax.microedition.lcdui.Image createImage(byte[] imageData, int imageOffset, int imageLength) static javax.microedition.lcdui.Image createImage(int width, int height, int ARGBcolor) static DirectGraphics getDirectGraphics(javax.microedition.lcdui.Graphics g) Comment Creates a mutable image that is decoded from the data stored in the specied byte array at the specied offset and length The method will return a newly created mutable Image with the specied dimension and all the pixels of the image dened by the specied ARGB (alpharedgreenblue) color Converts standard javax.microedition.lcdui.Graphics to DirectGraphics
standard Graphics to DirectGraphics, creating images with specied ARGB color and creating mutable images from the encoded image byte arrays. Creating an image from the byte array is done with the same semantics as in createImage() of Image. Creating a new Image with dimensions of 100 100 pixels and with red, 50% transparent, color can be done as follows:
DirectUtils.createImage( 100, 100, 0x77FF0000 );
FullCanvas
FullCanvas is used in midlets that need a full-screen painting area. The full screen is accessed simply by extending ones own canvas
482
Figure 20.9
class in FullCanvas. The biggest difference (after full-screen access) from the original Canvas class is that Commands cannot be added to FullCanvas. Pressing the softkey or other command buttons will result in keystroke events. These can be caught by overwriting the keyEvent(), keyPressed(), and/or keyReleased() methods in the Canvas class. There are also some new constants used for these key codes. All the normal key codes are reported to FullCanvas. The callback methods such as paint( Graphics g ) work with the same semantics as in Canvas. This means that converting some of an existing canvas to FullCanvas can be done by extending it in FullCanvas instead of Canvas (if the implementation does not use any Commands). Although it is said that in the Nokia UI API status indicators such as networking should be shown, there is little deviation from the Series 60 Platform. The Series 60 UI style guide (Nokia, 2001g) says that applications that take the whole screen should not show any indicators. This Time Tracker class shows how FullCanvas can be created and how key codes can be captured with it. Using the full screen is done simply by extending TTProjectCanvas from FullCanvas. The key events are captured by overwriting the keyPressed() method:
public class TTProjectCanvas extends FullCanvas . . . public void paint( Graphics aG ) { . . . } {
NOKIA USER INTERFACE CLASSES public void keyPressed( int aKey ) { switch( aKey ) { //Key was right cba key case FullCanvas.KEY_SOFTKEY2: { . . . // Switching away from FullCanvas iDisplay.setCurrent( iProjectForm ); break; } . . . default: { . . . break; } } } }
483
Sound
This class is used to play simple sound effects such as tones and digitized audio. MIDP 1.0 does not have an API for sounds, and therefore this extension is particularly needed for games. The Series 60 implementation supports WAV, RNG, AMR, MIDI, and all formats supported in the Media Server. WAV, AMR, and MIDI les can be initialized with the type FORMAT_WAV and RNG with the type FORMAT_TONE. The sound API (shown in Table 20.28) provides support for playing simple beeps of a given frequency and duration. The following example shows how to play a single beep for one second with a frequency of 2000 Hz:
Sound s = new Sound( 2000, 1000 ); s.play( 1 );
Sound objects can easily be recycled with the init() method. For example, if the object is constructed as a monotone beep it can be turned to, for example, WAV simply by calling the init with different parameters. Some runtime memory consumption can be lowered in this way. If, for example, the Sound objects are constructed in a loop for generating a tone sequence, it is quite certain that an outof-memory exception will occur at some point. The MIDP devices have restricted memory and resources, and therefore objects should be always recycled as much as possible.
484
Table 20.28 Methods in the Sound class Method static int getConcurrentSoundCount(int type) Comment Returns the maximum number of concurrent sounds the device can play for a specic audio type. Because the Media Server of the Series 60 Platform supports only one sound channel this method returns 1 for all types Gets the volume of the sound. This value is between 0 and 255 Gets the current state of Sound. States can be SOUND_PLAYING, SOUND_STOPPED, or SOUND_UNINITIALIZED Returns the supported audio formats as an int array. In the Series 60 Platform this returns both FORMAT_WAV and FORMAT_TONE Initializes Sound based on byte array data. Byte array can be in WAV, RNG, AMR, MIDI, or any other format that Media Server supports Initializes (Jep) Sound to play a simple beep. The frequency must be in the range 013 288 Hz and the duration must be at least 1 milliseconds This method is used for starting the playback from the beginning of a sound object. Loop count 0 indicates an endless loop; the maximum value of the loop is 255 Releases audio resources reserved by this, object. After this, the object must be initialized again The method will continue playback of the stopped sound object from the position from which it was stopped. Owing to the restrictions of Media Server this is not supported in the Series 60 Platform Sets the volume for the sound object. The gain must be between 0 and 255 Registers a listener for playback state notications This method will stop sound playback will and change the state to SOUND_STOPPED
The Symbian Media Server provides only one channel for sounds, so sounds cannot concurrently play. This means that if another sound is started before the rst one is nished, then the rst one is stopped and the second one starts immediately. Sounds follows the current prole. This means that if the midlet user has turned the warning and game tones off in the device (or emulator) no sounds will be played in Java. The key sounds are always turned off when the Sound class is used. This is done to avoid problems with the single sound channel.
NETWORKED MIDLETS
485
SoundListener
This interface is used by applications that need to monitor states of the Sound objects. By implementing this interface (Table 20.29) and adding it to Sound by the setSoundListener() method the application can receive the SOUND_PLAYING, SOUND_STOPPED, or SOUND_UNINITIALIZED events.
Table 20.29 Method in the SoundListener interface Method void soundStateChanged(Sound sound, int event) Comment Called when the playback state of a sound has been changed
20.3
Networked Midlets
The CLDC 1.0 Specication denes an abstract generic connection framework for all connections. This framework provides support for stream-based connections and datagrams. The congurations should not provide implementation and therefore the CLDC (connected limited device conguration) does not provide any protocol implementation. Proles that are on top of the congurations do not have to implement all protocols. Therefore, the currently used MIDP 1.0 specication demands implementation for HTTP 1.1 stream-based client connections only. This connection type is the only one supported in the Series 60 Platform.
20.3.1 Basics
20.3.3 HttpConnection
The HttpConnection interface is part of the package javax.microedition.io. This interface denes the necessary methods and constants for an HTTP (hypertext transfer protocol) connection. The
486
Connection
StreamConnectionNotifier
DatagramConnection
InputConnection
OutputConnection
StreamConnection
ContentConnection
HttpConnection
HTTP is a requestresponse application protocol that needs its parameters to be set before sending a request, and therefore it has three states: Setup (no connection, setting parameters), Connected (request send waiting response), and Closed (connection closed). The basic HttpConnection is made in the following fashion:
HttpConnection conn = (HttpConnection)Connector.open ("http://www.digia.com");
The connection is then in the setup state and the parameters can be set; for example:
conn.setRequestMethod( HttpConnection.POST );
The nal translation to the connected state is done by one of the following methods:
OVER-THE-AIR PROVISIONING
openInputStream(), openOutputStream(), openDataInputStream(), openDataOutputStream(), getLength(), getType(), getDate(), getExpiration().
487
Closure of the connection is done by the close() method in HttpConnection. The opened input or output streams must be also closed. The following example shows how an image can be downloaded from the Internet:
private Image loadPicture( String aUrl ) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); try { //Opening the connection to the logo HttpConnection conn = (HttpConnection)Connector.open( aUrl ); InputStream inputStream = conn.openInputStream(); byte [] nextByte= new byte[1]; //Reading the image byte by byte while ( ( inputStream.read( nextByte, 0, 1 ) )!=( -1 ) ) { baos.write( nextByte[0] ); } // Closing the connection conn.close(); inputStream.close(); } catch( IOException e ) { System.out.println( "loading the picture failed" ); } //Creating new image from the fetched byte array return Image.createImage( baos.toByteArray(), 0, baos.size() ); }
20.4
Over-the-Air Provisioning
Over-the-air (OTA) provisioning is a de facto standard that is provided by Sun Microsystems. The main goal of this recommended practice is to describe how the midlet suites can be deployed in devices. This standard should ensure interoperability between devices from all manufacturers and in that way make it easier for cellular operators to make their own MIDP services. Midlet suite vendors can expect all devices to have mechanisms that allow users to download suites to the device. Such a download can be done via the resident browser [e.g. (WAP) wireless application protocol] of the device or by some application that is written specifically for suite downloading. During the download and installation process the user should get basic information on the suite that is about
488
to be installed. This information is usually read from the Java application descriptor (JAD). After installation, the device sends notication of successful installation to the server. This gives an opportunity for cellular operators to sell midlet suites and to be sure that customers have successfully installed the suite. The user should have an opportunity to control the suites in the device once they are installed. This control is usually done by the Java application manager (JAM) application. JAM provides mechanisms for installing, browsing, launching, and removing the midlet suites.
(a)
(b)
(c)
(d)
Figure 20.11 Suite download: (a) installation; (b) the installed suite; (c) the Java application manager menu for the suite; (d) midlet suite information
SUMMARY
489
20.5
Summary
In this chapter and is Chapter 19 we have described the essentials of Java programming in the Series 60 Platform. In this chapter we have concentrated on use of the midlet UI framework in application development. All UI classes that the Series 60 Platform MIDP supports have been described. In addition, code examples have been used to show how the classes can be applied in UI implementation. The Series 60 Platform supports an extension to standard MIDP UI classes. This extension, which is provided by Nokia, supports also the use of sound in Java applications. The classes in the extension packages have also been described and used in programming examples. In addition to UI programming, communication support between midlets and midlet OTA provisioning have been covered.
Appendix
An example of a User Interface Specication
1 Example of How to Specify the Screen Layout
The main view is displayed after the ImagePlus application is launched. It displays two options: Open image and New image (Figure 1; see also Table 1). Selecting Open image displays a dialog view to the images folder. Selecting New image displays a view with a new image template.
491
Figure 1 Layout example of the main view Table 1 The main view layout Layout area Signal pane Context pane Title pane Navigation pane Battery pane Description of the layout area Displays the signal strength Displays the application icon <application icon> Displays the application name: ImagePlus <application title> Displays text: Start up <application startup> Displays the battery pane in idle state; the battery pane indicator is not displayed in the applications List type: single list with large icon Displays a large icon <open image> Displays a large icon <new drawing> Open image <image open> opens an existing image New image <image new> opens a new drawing template Note: no scrolling indicator arrows are needed Select <left softkey select> selects the highlighted item Back <right softkey back> displays the previous view
Main pane AB column, rst line AB column, second line C column, rst line C column, second line Control pane Left softkey Right softkey
492
(c) Sharpen <image color> submenu item opens the sharpen view. (d) Blur <image blur> submenu item opens the blur view.
EXAMPLE ON A USE CASE Table 3 Keypad functions in main view Key name Scroll up Scroll down Scroll left Scroll right Select key Send key End key Applications key Clear key Edit key (ABC key) * key # key Power key Voice key Description of the hardware key function
493
Scrolls the selection up Scrolls the selection down Scrolls the selection left Scrolls the selection right Opens the OK options menu or opens the selected list item In the idle state opens a list of recently called numbers; in the phone book, it calls the selected number Ends phone call; in applications, it goes to the idle state Press displays application grid: press and hold displays open applications list Clears characters in text-editing mode Opens the edit menu in the text-editing mode (note: this key can be pressed simultaneously with another key press) Opens the select symbol (special character table) dialog in text editors; see Chapter 10 for all possible functions of this key Changes the text input mode: see Chapter 10 for all possible functions of this key Powers the device up or down Activates the voice calling function
Table 4 Examples of a use case Use Case #: 1 Name Description Actor Preconditions Postconditions Opening image for editing User selects an image from the photo album to be edited in ImagePlus application. End user who starts using the application Application Launcher is open An image has been successfully opened to ImagePlus and user can start adding objects on top of it. The Startup view is displayed if no images exist in the photo album. 1. User selects the ImagePlus application from the application grid. 2. A startup view is displayed, the rst item highlighted. 3. The user selects the Open image item from the startup list. 4. The Photo album contents are displayed in a pop-up window. 5. The user browses the photo album contents and selects one image. 6. TheOpening image wait note is displayed while the system downloads the image to ImagePlus. 7. The opened image is displayed in the Main view. (2) The user exits the application by pressing Exit. ImagePlus application is closed. (5) If no photos exist in the photo album, pressing Cancel will display the Startup view again. (5) If the user selects a folder, the contents of the folder are displayed in a list. Opening image when an existing image in ImagePlus.
Success scenario
Exceptions
Dependencies
Glossary
Terms in bold in the denitions are also dened within this glossary. ACK: acknowledgement; a positive conrmation that a requested service has been completed successfully. ACL: (1) access control list; (2) asynchronous connectionless. Adapters: where data are in one form and are needed in a different form from how they are stored, adapters convert the data from the stored form to the required form. ADPCM: adaptive differential pulse code modulation. AH: authentication header. AIF: application information le; denes the icons, captions, capabilities, and supported MIME types of an application. API: application programming interface. APPARC: application architecture; provides a policy on how applications are stored in the le system. It also provides the basic framework for applications. AppTest: software by Digia Inc designed to help to test applications. App UI: handles application-wide aspects of the user interface, such as menus, starting and exiting views, and creating and destroying views. All Symbian OS applications should have one App UI. ARM: advanced risk machine. ARM4: a 32-bit instruction set and binary interface for ARM-based processors. If an application is compiled for ARM4, it can call only functions that have also been compiled for ARM4. ARMI: a 32-bit instruction set and binary interface for ARM-based processors. It can call methods compiled for ARM4 as well as THUMB. ARP: address resolution potential. ASSERT macros: macros ( ASSERT ALWAYS and ASSERT DEBUG) used to check the value of a boolean condition. Assert failure usually results in a panic. Assertion: a condition that must be true for the execution of the application to continue. Used for catching programming errors early. ASSP: application-specic standard port.
GLOSSARY
495
Audio streaming: a method of playing audio where the application can concatenate new audio clips to the currently playing clip, providing a continuous stream of audio to the user. Avkon: The Series 60 platform standard user interface toolkit built on Symbian Uikon technology. Base porting: an activity where Symbian OS is ported to a new hardware platform. BC: binary compatibility; BC determines whether an application is able to use an API without recompiling. If BC is kept between revisions of an API, applications compiled for one revision work with all revisions. BIF: BIO information le. BIO: bearer-independent object; used for sending binary data over various bearers, such as SMS or WDP. Black-box testing: testing without knowledge about the implementation of a module. This ensures that the module fullls the API it claims to export. The opposite is white-box testing. BMP: Windows bitmap. BT: British Telecommunications plc. C32: serial communications server; handles the serial ports of a device. It provides the applications with a generic interface to serial-like communications. CBA: command button array on Series 60; consists of the functions bound to the two softkeys. CCP: compression control panel. CDC: connected device conguration. CHAP: challenge handshake authentication protocol. Checkbox: a special type of list, where the user can choose several items from a list of choices. CLDC: connected limited device conguration; a Java standard that denes common hardware requirements and a set of APIs for lowend consumer devices. CONE: control environment; provides the framework for creating and accessing user interface controls. Includes all classes starting with the prex CCoe. Control: elements that own and handle the drawing on a rectangular area on the screen. They can respond to user actions and they can consist of other controls. CRE: cyclic redundancy check. CSD: circuit-switched data; the generic 9600 bps GSM data connection. CSY: Serial communications module; provides an implementation of a serial port to the Serial communications server.
496
GLOSSARY
DBMS: database management system on Symbian OS; provides easyto-use database functionality to the applications. DCE: data circuit terminating equipment. DEA: data element alternative. Delayed function call: interrupt handlers must be very fast and small in order to be able to serve all interrupts. If the handling of an interrupt takes more time, the interrupt handle invokes a delayed function call and exits. The kernel runs the function after the interrupt handle has completed. DES: (1) data encryption standard; (2) data element sequence. Descriptors: provide a type-safe and easy-to-use way of accessing, manipulating, and storing strings and binary data. DFC: delayed function call. Dialog: used for bringing information to the users attention or for requesting information from the user. They take up screen space and intercept key commands temporarily until the user acknowledges the dialog. If possible, a setting page should be used instead to provide a user interface with Series 60 feel. DLL: dynamic link library. DMP: device management protocol. DNS: domain name service; provides a mapping between IP addresses and domain names. DTE: data terminal equipment. DTMF: dual-tone multifrequency; a method of sending numbers and a few special symbols via analog phone system. It is used for selecting the phone number of the remote party at the beginning of a call. DUNP: dialup networking prole. EDGE: an evolution of the GSM, providing faster wireless data connections. Enbs: Symbian OS enumeration for NBS. Engine: sometimes called the model of the ModelViewController design pattern. It is the part of application that manages the nonuser-interface aspects of the program logic. The engine should be transferable between different user interface styles. ESP: encapsulating security payload. ETel: the telephony server on Symbian OS; provides access to the telephony functions of a mobile phone, such as GSM, GPRS, and fax. FEP: front-end processor; a module that intercepts keyboard events from editor controls. Some events are allowed through, but some events are used, for example, to implement the T9 input method. FIR: fast infrared; a fast version of the IrDA protocol. It provides speeds up to 4 Mbps. Form: a collection elds, that the user can ll. Dialogs use forms for showing the actual items.
GLOSSARY
497
FPU: oating point unit. GCC: gnu compiler collection. GDI: graphics device interface. GIF: graphics interchange format. GPRS: General Packet Radio System; an extension of GSM, which provides packet data service. Grid: user interface control that provides horizontal and vertical browsing of list elements. GSM: global system for mobile. GUI: graphical user interface. HCI: host controller interface. HSCSD: high-speed circuit-switched data; a fast GSM data connection providing speeds from 14 400 bps upwards. HTML: hypertext markup language. HTTP: hypertext transfer protocol. IAP: Internet access point. ICMP: Internet control message protocol. Icons: small graphical elements that convey a piece of information to the user. Icons are almost always embedded inside MBM les. IDE: integrated development environment. IMAP4: Internet mail access protocol; allows connection to and management of mailboxes on remote hosts. Also permits selective download of messages. IMC: Internet Mail Consortium; maintains, develops, and promotes standards for e-mail in Internet. IP: Internet protocol. IPSec: Internet security protocol. IrCOMM: emulates the RS-232 protocol on IrDA. It allows implementation of IrDA support for legacy applications. IrDA: Infrared data association; maintains and promotes the infrared protocol stack with the same name. The protocol hides the implementation details of infrared communications from the applications and allows them to communicate with another IrDA-capable device with a simple socket API. IrLAN: infrared local area network. IrLAP: infrared link access protocol. IrLMP: infrared link management protocol; establishes and maintains infrared links between applications. It provides services such as device discovery and link multiplexing. IrMUX: a socket protocol providing an unreliable datagram service through the IrDA LM-MUX layer (IrDA Link Management MUX). IrObex: infrared object exchange. IrTinyTP: infrared tiny transport protocol.
498
GLOSSARY
ISM: industrial, scientic, and medical; a radio band freely usable for industrial, scientic, and medical applications. ISP: Internet service provider. ITC: interthread communication. J2ME: Java 2 Micro Edition; a small version of the Java 2 family intended for mobile phones and set-top boxes. JAD: Java application descriptor; contains an advertisement on a Java application and directions to download it. JAM: Java application manager. JAR: Java archive; contains the class les and resources of a Java application. JFIF: JPEG le interchange format. JNI: Java native interface. JPEG: Joint Picture Expert Group. JRN: Java runtime environment. KVM: K Virtual Machine; a Java virtual machine for low-footprint applications. It is used in the MIDP and CLDC platforms. L2CAP: logical link control and adaptation protocol. LAF: look and feel; the part of the user interface style that denes the actual appearance of the applications. LAN: local area network. LANAP: local area network access prole. LCP: logical control protocol. LDD: logical device driver. LIF: Location Interoperability Forum. LIFO stack: last-in, rst-out stack. Lists: sometimes called list boxes; lists show the user an array of textual or graphical elements. If the list is interactive, the user can choose one or more elements from the list. LMP: link management protocol. LOC: localization le; contains the strings of an application that are displayed to the user. There is one LOC le for each application and language. MARM: multiprocess advanced risk machine; a general name for a target build of type ARMI, ARM4, or THUMB. MBM: multi-bitmap le; a collection of bitmaps. It is used in Symbian OS because it is an efcient way of storing and retrieving a large number of bitmaps. MD5: encryption algorithm. Menu: menus or pop-up menus contain a list of actions the user can perform. The list is brought up only when needed when the user presses, for example, the Options softkey or selection key (context-sensitive menu).
GLOSSARY
499
MHTML: denes how HTML documents can be embedded inside e-mail messages. Midlet: Midlet is an application suite written for the MIDP platform. MIDP: mobile information device prole; built on CLDC and denes characteristics for a mobile device. MIME: multipurpose Internet mail extension; extends the Internet mail format to allow different character sets, nontextual, and multipart messages. MMS: multimedia message service; a standard that allows multimedia messages to be sent between mobile devices. MMSC: multimedia message service center. MTM: message-type module; a plug-in module that contains the implementation of a messaging method, such as SMS, IMAP4, or POP3. An MTM is divided into UI MTM, UI Data MTM, Client-side MTM, and Server-side MTM. MVC: Model-View-Controller. NACK: negative acknowledgment; see ACK. NBS: narrow-band sockets; a protocol, that is no longer used. NBS port numbers are still in use in smart messaging for distinguishing between different smart message types. NIF: network interface. NifMan: network interface manager; responsible for network connections, such as dial up features. Note: a simple dialog-type control. A note can be global to show it on top of any application, or local to show it only in one application, and a tone can be attached to the note to attract the users attention. Examples of notes are warning note, error note, and progress note. OBEX: object exchange. Object provider: this mechanism allows controls to access other controls in the same user interface context. Examples are control scrollbars, which access the scrollbar on CBA. OCP: open-closed principle. OCR: optical character recognition. OEM: original equipment manufacturer. OMA: Open Mobile Alliance. OOM: out-of-memory. OSI: open systems interconnection. OTA: over the air. Pane: a part of display area dedicated to a specic purpose. The Series 60 platform denes a list of panes, which should be the same for all applications, to show, for example, the application name, signal strength, and CBA. PAP: PPP authentication protocol.
500
GLOSSARY
PCM: pulse code modulation. PDD: physical device driver. PDI: personal data interchange. PDU: (1) protocol data unit; (2) protocol description unit. PIM: personal information management; a collection of functions such as calendar, e-mail, and a contacts manager. PLP: Psion link protocol; a protocol that was used in communication between a PC and a Symbian OS device before the mRouter protocol. PNG: portable network graphics. Polymorphic interface library: a DLL that exports only one method. That method is commonly used for creating an object with a certain M-class interface. All methods accessed from the class are virtual methods and thus need not be exported. POP3: Post Ofce Protocol; allows connection to Internet mailboxes on remote hosts and retrieving the mail. Not as advanced as IMAP4. PPM: pulse position modulation. PPP: pout-to-point protocol. PRT: protocol module. PSL: Psion link protocol. Query: like a note, except the user is asked to enter a piece of information. Radio button: a special type of list, where the user can choose one from a list of choices. RARP: reverse address resolution protocol. RAS: remote access server. RFCOMM: emulates the RS-232 protocol on top of L2CAP. It allows implementation of Bluetooth support for legacy applications. Rich text: text that can contain several types of fonts, styles, and other control information. RTTI: runtime-type information; allows C++ applications to make decisions based on the runtime type of an object. Not supported in Symbian OS. SAP: service action point. SCO: synchronous connection-oriented. SDP: service discovery protocol; allows applications to register and query Bluetooth services available on the device. SDP UUID: service discovery protocol universally unique identier; a 128-bit quantity used by Bluetooth to identify service classes, services, and protocols. SDU: service data unit. SendUI: implements the part of the user interface that is needed for sending a message. The application just needs to embed SendUI and implement parts that specify what is sent.
GLOSSARY
501
Setting page: like a dialog, but it allows modication of only one setting and covers the whole screen area. It gives the user better and more Series 60 like visual feedback than does a dialog. A setting page can be embedded inside a setting view. Setting view: a collection of setting pages. It shows a list of settings that can be modied, and when the user chooses a specic setting, the corresponding setting page is opened. Most of the settings in default applications on the Series 60 platform are accessed via setting views. Sinewave tone: sound composed of a single sinewave, providing only one tone of a certain frequency. SIR: slow infrared; the original IrDA protocol. It provides speeds up to 115.2 kbps. SIS: Symbian Installation System: allows packaging an application into a le, from which the application can be installed on a Symbian OS system. Smart messaging: a concept where special messages such as ring tones and calendar entries can be sent via SMS. SMIL: synchronized multimedia integration language. SMSC: short message service center. SMTP: simple mail transfer protocol; a standard for sending mail from one host to another. It is the backbone of the Internet mail system. SPP: serial port prole. SSH: secure shell. SSL: secure socket layer. Static interface library: a DLL where all the methods and classes available are accessed via exported methods. SyncML: a standard that allows synchronizing the calendars and contacts of mobile devices with each other, or with a PC host. Tabs: a complex user interface can be divided into specic views of the user interface. The top part of the screen can contain tabs (i.e. a horizontal list of the views as text or icons). TCP: transmission control protocol. TCP/IP: transmission control protocol/Internet protocol. THUMB: a 16-bit instruction set and binary interface for ARM-based processors. Used primarily for ROM-based applications If an application is compiled for THUMB, it can call only functions that have also been compiled for THUMB. TLS: transfer layer security. TSY: Telephony control module. UART: universal asynchronous receivertransmitter; the hardware component that manages serial ports. UCD: user-centered design. UDP: user datagram protocol. UED: user environment design.
502
GLOSSARY
UID: unique identier. Uikon: generic Symbian user interface toolkit on which all devicespecic toolkits build on. Provides generic elements such as dialogs, and other controls. UML: user modelling language. UMTS: Universal Mobile Telecommunications System; one of the major third-generation systems being developed. It will offer data rates up to 2 Mbit s1 with global roaming and other advanced capabilities. URL: universal resource locator. USB: universal serial bus. UTF: unicode transformation format. UUID: universally unique identier. vCalendar: a format for calendar access. Allows sending calendar entries from one device to another and scheduling meetings between participants. vCard: a format for business contacts. Allows sending contact entries from one device to another. View: an application displays the user data inside views. One application can contain several views with the means to switch between views linking parts of user data to each other. A view can also be activated from another application. VM: virtual machine. vMail: a Symbian-dened format for mail messages. It is based on the same stream and property formatting principle applied in vCalendar and vCard. WAE: wireless application environment. WAP: wireless application protocol. WDP: wireless datagram protocol. White-box testing: testing done generally by the implementer of a module. The test cases are designed to cover a large portion of the normal and exceptional ows of control in a module. See also black-box testing. Window: all draw commands are performed ultimately on windows. The window server converts the draw commands to hardware drawing instructions. WINS: Windows single process. WML: wireless markup language. WSP: wireless session protocol. WTAI: wireless telephony application interface. WTLS: wireless transition layer security. WTP: wireless transaction protocol. XML: extensible markup language.
References
Allin J (2001) wireless Java for Symbian Devices. John Wiley, New York. Bevan N (2002) Cost-effective User-centered Design, available at www.usability.serco.com/trump/index.htm. Beyer H, Holtzblatt K (1998) Contextual Design: Dening Customer-centered Systems. Morgan Kaufmann, San Francisco, CA. Binder R (1999) Testing Object-oriented Systems: Models, Patterns, and Tools. The Addison-Wesley Object Oriented Technology Series. Addison-Wesley Longman, Reading MA. Booch G, Rumbaugh J, Jacobson I (1999) The Unied Modeling Language. Addison-Wesley, Reading, MA. Buschmann F, Meunier R, Rohnert H, Sommerlad P, Stal M (1996) Patternoriented Software Architecture, Volume 1: A System of Patterns. John Wiley, New York. Cai J, Goodman D (1997) General Packet Radio Service in GSM, IEEE Communications Magazine October: 122131. CMG, Comverse, Ericsson, Nokia, Logica, Motorola, Siemens, Sony Ericsson (2002) MMS Conformance Document, Version 2.0.0, available at www.forum.nokia.com. Connected, Limited Device Conguration (JSR-30), Version 1.0, Sun Microsystems, 2000. Available as http://jcp.org/aboutJava/commmunityprocess/nal/ jsr030/index.html Doraswamy N, Harkins D (1999) IPSec, The New Security Standard for the Internet, Intranets, and Virtual Private Networks. Prentice Hall, New Brunswick, NJ. Douglass B (2001) Doing Hard Time: Developing Real-time Systems with UML, Objects, Frameworks, and Patterns. Addison-Wesley, Reading, MA. Dray S (1998) Structured Observation, tutorial presented at CHI-SA (Pretoria, South Africa), CHI 2001 (Seattle, WA), CHI 2000 (The Hague, Netherlands), CHI 1999 (Pittsburgh, PA), CHI 1998 (Los Angeles, CA), CHI 1997 (Atlanta, GA), and CHI 1996 (Vancouver, BC). Dray S, Mrazek D (1996) A Day in the Life of a Family: An International Ethnographic Study, in D Wixon, J Ramey (eds), Field Methods Casebook for Software Design John Wiley, New York, 145156. ETSI (1998) ETSI GSM 02.60: Service Description, Stage 1 (v 7.0.0), ETSI, www.etsi.org<http://www.etsi.org>. Fewster M, Graham D (1999) Software Test Automation: Effective Use of Test Execution Tools. ACM Press, Addison-Wesley, Reading, MA.
504
REFERENCES
Gamma E, Helm E, Johnson R, Vlissides J (2000) Design Patterns: Elements of Reusable Object-oriented Software. Addison-Wesley Longman, Reading MA. Hoikka K (2001) Design Patterns in EPOC Software Development, masters thesis, Department of Information Technology, Lappeenranta University of Technology, Finland. Holmqvist L (1999) Will Baby Faces Ever Grow Up?, available at www.viktoria.se/groups/play/publications/1999/babyfaces.pdf. Hynninen T, Kinnunen T, Liukkonen-Olmiala T (1999) No Pain, No Gain: Applying User-centered Design in Product Concept Development, in S Dray, J Redish (eds), Interact 99. The British Computer Society and IFIP TC 13, 201205. ISO 13407 (1999) Human-centered Design Processes for Interactive Systems. ISO, Geneva. Jipping M (2002) Symbian OS Communications Programming . Symbian Press, John Wiley, New York. Larmouth J (1999) ASN.1 Complete. Morgan Kaufmann, San Francisco, CA. Lindholm T, Yellin F (1999) The Java Virtual Machine Specication, second edition, Addison-Wesley, Reading, MA. Martin R (1996) Open Closed Principle. C++ Report, January, available at www.objectmentor.com/resources/articles/ocp.pdf. Mery D (2001) Symbian OS version 6.x: Detailed Operating System Overview, available at www.symbian.com/technology/symbos-v6x-det.html. Mayhew D (1999) The Usability Engineering Lifecycle: A Practitioners Handbook for User Interface Design. Morgan Kauffmann, San Francisco, CA. Nelson E (2002) Interview of Kent Beck and Alan Cooper: Extreme Programming vs. Interaction Design, available at www.fawcette.com/interviews/ beck cooper/default.asp. Nielsen J (1992) Finding Usability Problems through Heuristic Evaluation, Conference Proceedings of Human Factors in Computing Systems. May 37, 1992. Nielsen J (1994) Usability Engineering . Morgan Kauffmann, San Francisco, CA. Nielsen J, Norman D (2002) User Experience: Our Denition, available at www.nngroup.com/about/userexperience.html. Nokia (2000) Smart Messaging Specication Revision 3.0.0, Nokia, Finland; available at www.forum.nokia.com. Nokia (2001a) Bluetooth Application Development for the Series 60 Platform, Version 1.0, Nokia, Finland; available at www.forum.nokia.com. Nokia (2001b) Nokia Coding Idioms for Symbian OS, Nokia, Finland; available at www.forum.nokia.com. Nokia (2001c) Designing Applications for Smartphones: Series 60 Platform Overview, Nokia, Finland; available at www.forum.nokia.com. Nokia (2001d) Nokia Multimedia Messaging White Paper, Nokia, Finland; available at www.forum.nokia.com. Nokia (2001e) Nokia Series 60 Games UI Style Guide, Nokia, Finland; available at www.forum.nokia.com. Nokia (2001f) Nokia Series 60 SDK for Symbian OS, Nokia, Finland; available at www.forum.nokia.com.
REFERENCES
505
Nokia (2001g) Nokia Series 60 UI Style Guide, Nokia, Finland; available at www.forum.nokia.com. Nokia (2001h) WAP Service Developers Guide for the Series 60 UI Category Phones, Version 1.2, Nokia, Finland; available at www.forum.nokia.com. Nokia (2002) How to Create MMS Services, Version 3.0, Nokia, Finland; available at www.forum.nokia.com. Norman D (1999) The Invisible Computer: Why Good Products Can Fail, the Personal Computer is so Complex, and Information Appliances are the Solution. MIT Press, Cambridge, MA. Perry W (2000) Effective Methods for Software Testing, Second Edition, 2000, John Wiley & Sons, Inc. Printed in USA. in R Elliot (ed.), Canada. Pora H (2002) Application Size Optimization in Mobile Environment, masters thesis, Department of Information Technology, Lappeenranta University of Technology, Finland. Pressman R (1999) Software Engineering: A Practitioners Approach. McGrawHill International Editions, New York. Raskin J (2000) The Humane Interface . ACM Press, Addison-Wesley, Reading, MA. Rose M (1990) The Open Book: A Practical Perspective on OSI . Prentice Hall, New Brunswick, NJ. Ruuska S, V aa n anen-Vainio-Mattila K (2000) Designing Mobile Phones and Communicators for Consumers Needs at Nokia, in E Bergman (ed.), Information Appliances and Beyond; Interaction Design for Consumer Products, Morgan Kaufmann, San Francisco, CA, 169204. Schneier B (1995) Applied Cryptography: Protocol, Algorithms, and Source Code in C , second edition, John Wiley, New York. Snyder C (2001) Paper Prototyping: Article on IBM DeveloperWorks, available at www-106.ibm.com/developerworks/library/us-paper/?dwzone= usability. Stallings W (1999) Data and Computer Communications, sixth edition, Prentice Hall, New Brunswick, NJ. Steele G, Gosling J, Bracha G (2000) The Java Language Specication, second edition, ed. B Joy, Addison-Wesley, Reading, MA. Symbian (2002a) UIQ for Symbian OS v7.0, available at www.symbian.com/ technology/ui/uiq.html. Symbian (2002b) Symbian OS User Interfaces, www.symbian.com/technology/devices.html. SyncML Initiative (2002c) SyncML Sync Protocol 1.1 White Paper, available at www.syncml.org. Tasker M, Allin J, Dixon J, Forrest J, Heath M, Richardson T, Shackman M (2000) Professional Symbian Programming. Mobile Solutions on the EPOC Platform. Wrox Press, Birmingham, UK. WAP Forum (2001) WAP MMS Architecture Overview, available at www.wapforum.org. WAP Forum (2002a) WAP MMS Client Transactions Specication, available at www.wapforum.org. WAP Forum (2002b) WAP MMS Encapsulation Protocol, available at www.wapforum.org.
Index
ABLD 56, 58, 60, 77, 147 Active objects see also CActive Framework 87 Active scheduler 87, 88, 179 see also CActiveScheduler Adapters 38, 41, 130 Advanced risk machine see ARM AIF AIF Builder 54, 55, 62, 64, 65, 67 AIF Builder project les (.aifb) 62, 64 AIF les (.aif) 57, 67 AIF Icon Designer 54 AknListBoxLayouts SetupFormAntiFlickerTextCell() function 233 SetupGridFormGfxCell() function 233 SetupGridPos() function 233 SetupStandardGrid() function 233 AknPopupLayouts 227, 230 API 21, 29, 31, 33, 38, 47, 52, 78, 85, 86, 89, 148, 195, 196, 205, 251, 258, 300, 310, 311, 315, 318, 323, 326, 332, 341343, 349, 355, 356, 371374, 376, 401, 403, 410, 426428, 433, 439, 440, 449, 477, 478, 482, 483 APPARC 58, 397 Application Application architecture 24, 39, 41, 47, 54, 166, 168, 170, 173, 179, 235 Application binary les (.app) 54, 77 Application engines 7, 170, 371, 410, 412 Application framework 7, 9, 10, 15, 16, 34, 55, 165, 167, 168, 173, 193, 304, 439, 440 Application tester 154, 155, 157 Application Wizard 52, 54, 56 Deployment 54, 60 Launching 16, 24, 165, 166, 173, 179, 276, 428, 445, 488 Application launch-and-swap key 22 Application programming interface see API Applications key 112, 113, 493 AppTest 154156, 159161 App UI 48, 170, 304 ARM 5, 59, 60, 80, 294, 301, 313 ARM4 56, 59 ARMI 5860 Assertion EUNITASSERT 149, 150 Attachments 318, 375, 382, 385, 402405 Audio Audio clips 30, 283 Audio streaming 353
508
INDEX
Audio (continued ) MIDI 279, 283, 291, 483, 484 Recording 279, 288291 Ringtones 299, 395 Sinewave tones 279, 281, 483 WAV 279, 283, 285, 395, 483 Avkon 16, 21, 24, 25, 33, 39, 40, 47, 52, 58, 108, 165, 166, 172174, 176, 183, 185, 186, 193, 195, 196, 211, 223, 244, 262, 264, 266, 269, 294, 296 Backup and Restore 409, 411 Base Porting 5, 7, 17, 24, 292, 300, 302, 306, 317 Battery charge status 26 Battery pane 196, 204, 491 BC 215, 293 Bearer-independent object BIF le 396 Narrow-band socket 397 NBS 397 Binaries ARM4 59 ARMI 59, 60 THUMB 56, 59, 305 Binary compatibility see BC BIO 30, 375, 396, 421 see also Bearer-independent object Bitmaps Bitmap converter 54, 67 bmconv 54 Multi-bitmap les (.mbm) 67, 246, 252 Black-box testing 131, 144 bldmake 55, 56, 147 Bluetooth Bluetooth security manager 330, 356, 357, 361, 363 L2CAP 29, 329, 330, 351, 356 LMP 330 RFCOMM 29, 329, 330, 351, 356, 364, 415
SDP 29, 329, 330, 356358, 361, 364, 366, 367 bmconv 54 BSD sockets 354 Build tools ABLD 58, 60 aif le 65 aifb le 64 Application Wizard 52, 54, 56 bldmake 55, 56 bmconv 54 dsp le 59 GCC 54, 55, 70 inf le 56 makmake 55, 56, 59 mmp le 57 Perl 55, 70 pkg le 62
C class 8183, 85, 331 C32 311, 328, 343 CActive Cancel() function 349 DoCancel() function 321, 344, 358, 360 iStatus member 348 RunL() function 321, 344, 348, 358, 360, 362 CActiveScheduler Add() function 361 CAknApplication OpenFileL() function 173, 288 CAknAppUi HandleCommandL() function 172, 176, 186, 273, 304, 306 CAknCaleMonthStyleGrid 228, 229 CAknConrmationNote 247 CAknDialog DynInitMenuPaneL() function 174, 176, 181, 239 CAknDocument 40, 173, 193, 304 CAknDoubleNumberStyleListBox 217, 223, 224 CAknDurationQueryDialog 259 CAknErrorNote 249
INDEX
509
CAknFloatingPointQueryDialog 259 CAknForm DeleteCurrentItemL() function 242 EditCurrentLabelL() function 242 QuerySaveChangesL() function 242 SaveFormDataL() function 242 CAknGrid SetLayoutFromResourceL() function 231 SetLayoutL() function 475 CAknIndicatorContainer 203 CAknInformationNote 188, 248, 305 CAknListQueryDialog 261, 263 CAknMarkableListDialog 223, 225 CAknMultilineDataQueryDialog 259 CAknNavigationControlContainer PushL() function 263 CAknNavigationDecorator MakeScrollButtonVisible() function 201 SetScrollButtonDimmed() function 201 CAknNaviLabel 201 CAknNoteDialog SetTextL() function 246 SetTextNumberL() function 246 SetTextPluralityL() function 246 CAknNumberQueryDialog SetMinimumAndMaximum() function 258, 259 CAknPinbStyleGrid 228, 229 CAknPopupList 226, 227, 262 CAknProgressDialog 251, 252 CAknQdialStyleGrid 228, 229 CAknQueryDialog SetPromptL() function 256 CAknSelectionListDialog 223225 CAknSettingItem 267 CAknSettingItemArray 267 CAknSettingItemList 267
CAknSettingPage 268, 269, 271 CAknSettingStyleListBox 217, 218, 267 CAknSinglePopupMenuStyleList Box 218, 227, 230, 263 CAknSingleStyleListBox 216, 220, 224 CAknSmallIndicator 205 CAknStaticNoteDialog 249 CAknTextQueryDialog 257 CAknTimeQueryDialog 259 CAknTitlePane 196 CAknView DoActivateL() function 273, 276 DoDeactivate() function 273, 274 CAknViewAppUi ActivateLocalViewL() function 273 CAknVolumeControl 202 CAknWaitDialog 251 CAknWaitNoteWrapper 252 CAknWarningNote 248 CApaApplication 78, 169, 179 CApaDocument 169, 179 CArrayFixFlat 73, 76, 84, 91, 92, 146149, 263 CBA Object provider mechanism 207, 208 CBase 72, 74, 76, 81, 83, 148, 149, 151, 168, 176, 273, 281, 378 CBaseMtm 388, 390 CCoeControl 48, 50, 173, 174, 176178, 182, 196, 203, 208, 400 CCommsDatabase 319 CEikApplication AppDllUidL() function 168, 169 CreateDocumentL() function 168, 169 CEikAppUi HandleCommandL() function 172, 186
510
INDEX
CEikButtonGroupContainer 207, 208 CEikColumnListBox 226 CEikDialog 207, 223, 239, 251 CEikDocument CreateAppUiL() function 170, 172, 179 CEikEnv ConstructAppFromCommand LineL() function 179 CEikFormattedCellListBox 226, 227, 235 CEikListBox CreateScrollBarFrameL() function 222 CurrentItemIndex() function 221, 228 HandleItemAdditionL() function 221 HandleItemRemovalL() function 222 ItemDrawer() function 210, 226, 230, 233 CEikScrollBarFrame 222 CEikStatusPane ControlL() function 196 MakeVisible() function 205, 206, 442, 457, 473 SwapControlL() function 206 CEikTextListBox 211, 220 Certicates 63, 339, 340 Chunk 78, 80, 82 CImEmailMessage 382, 384 CImHeader 382, 383, 385 CImImap4GetMail 385 CImPop3GetMail 385 CImSmtpSettings 384 Classes see also specic classes C class 8183, 85 M class 282, 289, 320, 431 CLDC 18, 52, 425435, 438, 439, 441, 447, 485 Cleanup framework 9 Cleanup stack 37, 44, 45, 81, 82, 85, 89, 139, 140, 205, 226, 263 Clear key 493
Client-side MTM 318, 379 Clientserver framework see also RSessionBase Client-side API 89, 319, 343, 374 Session 86, 89, 311, 318, 320 CListBoxView 210, 235, 263 CListItemDrawer ColumnData() function 226 FormattedCellData() function 226, 230, 233 CMdaAudioOutputStream 285, 286 CMdaAudioPlayerUtility 283, 284 CMdaAudioRecorderUtility 288 CMdaAudioToneUtility 281, 282 CMsgBioControl 398 CMsvEntry 377, 378, 383, 388390 CMsvServerEntry 377 CMsvSession DeInstallMTMGroup() function 381 InstallMTMGroup() function 381 CMsvStore 383, 384 CMtmGroupData 380, 381 Command button array 174, 183, 185, 206208, 256, 262, 274, 304, 450, 453 see also CBA Communication modules Message-type modules (.mtm) 318, 375 Protocol modules (.prt) 313, 316, 350, 371 Telephony control modules (.tsy) 316 Communications BSD sockets 354 Comms database 319 Communications architecture 17, 309, 319, 341, 374 Communications servers 17, 31, 165, 309311, 341343, 371
INDEX
511
Connectivity 27, 28, 322, 334, 406 Device discovery 315, 349, 354, 355 ETel 311, 317, 328, 329, 343, 371373, 379 Flow control 313, 315, 324, 325 Internet Access Point 316, 319 Message server 38, 310, 311, 318, 320, 342, 374377 NifMan 316, 328, 329, 343, 351, 414 RS-232, 28, 311, 313, 314, 321, 323, 324, 326, 334, 343346 Serial comms 310, 311, 313, 314, 317 Service resolution 316 Socket 17, 38, 78, 310, 311, 313, 315317, 320, 324, 326, 328, 329, 341343, 349351, 354, 371, 374 Telephony 7, 17, 38, 292, 302, 303, 310312, 316, 317, 342, 343, 371, 374, 376 UART 313, 333 Compound controls 189 Concept design 93, 94, 99101, 103, 129, 131 CONE 58, 166, 168, 172, 173, 176, 191, 192, 293 Connected Limited Device Conguration 52, 425431, 435, 439, 485 see also CLDC Connectivity Backup and Restore 409, 411 Device management 27, 421, 422 Symbian Connect SDK 12, 407, 416 Synchronization 17, 323, 406, 407, 410, 419 vMail 416 Console Console programs 134, 144
Construction 37, 44, 45, 75, 82, 145, 171, 195, 201, 220, 228, 247, 273, 277, 287, 453, 465 Context pane 196198 Controls Avkon 16, 25, 40, 196, 223 Check box 270 Dialog 25, 63, 207, 208, 223, 239, 241, 244, 299, 305, 490 Grid 25, 228 Icons 119, 225, 258 Lists 108, 118, 210, 269, 298, 364, 369, 379 Pop-up menu 25, 26 Radio button 268, 465 Rich text 405 Uikon 39, 206, 294296 Cooperative multitasking 79, 87 CPort 314 CProtocolBase 316, 317 CProtocolFamilyBase 316, 317 CPU 294, 300, 301 Crystal 10 CSD 27, 28, 33, 138, 139, 316, 331, 392 CSendAppUi 49, 174176, 180, 181, 401, 403, 404 CSendAs 318, 387, 401 CSerial 314 CServProviderBase 316, 317 CSMSHeader 388 CSY 310, 311, 313, 314, 343, 345, 346, 349 CTextListBoxModel ItemTextArray() function 221, 236 Customization UikLAF 295
DBMS 319 Debugger 134, 135, 142144, 147, 151, 152 Decorators 199, 201, 202 Delayed function call 313 see also DFC Descriptors 15, 71, 79, 8486, 90, 92, 188, 197
512
INDEX
Design pattern Adapter 15, 35, 41, 42, 235 Modelviewcontroller 15, 35, 38, 71, 210 MVC 3840, 50, 210 Observer 15, 35, 40, 42, 43, 50, 71, 267, 271, 287, 321 observer 210 State 15, 35, 43, 44, 48, 50, 174 Device discovery 325 Device drivers Logical device drivers (.ldd) 301 Physical device drivers (.pdd) 301, 302 Device Family Reference Design Crystal 10 Pearl 10 Quartz 10 Device management 27, 327 DFC 313 DFRD see Device Family Reference Design Dialogs CAknDialog 239 CEikDialog 207, 223, 251 DLLs Dynamic interface library 56 E32Dll() function 180 Freezing 77 Plug-in modules 302, 309, 312, 315, 375 Provider libraries (.app, .prt, .csy etc.) 56, 71, 77 Shared libraries (.dll) 56, 71, 72, 77, 79 Static interface library 56 DNS 354, 410 Document 25, 40, 47, 56, 64, 72, 90, 91, 113116, 118, 166, 168171, 239, 276, 304, 339, 395, 401 Domain name service see DNS dsp le 59 dsw le 58
DTMF 281 Dynamic link library see DLLs EDGE 429 Edit key 23, 24, 112 Editors Editor cases 121, 242 Input modes 113, 121, 203, 242, 244, 473 Numeric keymap 243 Special character table 242, 244, 493 Eikon 16, 24, 41, 47, 166, 179, 204, 297, 305 E-mail 2, 3, 14, 17, 2730, 34, 106, 245, 318, 335, 375, 381383, 385, 386, 405, 408 Emulator Emulator builds 55 End key 22, 493 Engine 34, 40, 45, 47, 49, 50, 56, 58, 7173, 81, 82, 8992, 165, 166, 168, 174, 234237, 272, 303, 306, 319, 327 see also MVC Entry function 77, 80 EPOC 68, 60, 78, 175, 177, 179, 301 EPOCROOT 52, 54, 60 ER5 302, 303, 305 ESK 316 ESock 311, 315, 328 ETel 311, 317, 328, 343, 372, 373, 376 EUnit 152 EUNITASSERT 149, 150 EUNITDECLARETESTCASETABLE 148 EUNITTESTCASE 147 Eunitdebugrunner 146, 147, 151153 EUser 58, 79, 165 Events Key events 176, 180, 181, 191193, 222, 274, 456, 482 Pointer events 191, 456
INDEX
513
Exceptions Leaving 83, 300, 332 Out-of-memory 84, 277, 483 TRAP 83, 84 Trap harness 83 User.:Leave() 83 Executables Executable les (.exe) 56 Libraries (look DLLs) 146, 234, 295, 314 EXPORTC 78, 8285, 9092, 179 Extensible markup language see XML Fast infrared see FIR Fault tolerance 139 Fax 318, 341, 373, 380 FEP 203 File management Direct store 56 Permanent store 56 Find pane 209 FIR 325 Flow control 313, 315, 324, 325 Forms CAknForm 242 Framework 7, 9, 10, 15, 16, 24, 28, 34, 40, 47, 55, 71, 79, 86, 87, 89, 145148, 151, 165, 168, 172174, 179, 180, 182, 187, 189, 191193, 195, 210, 264, 277, 295, 299, 300, 304, 375, 376, 398, 399, 408, 425, 435, 440, 449, 486 Front-end processor 203 see also FEP Full-screen mode 205 Functional specication 100102 Functional testing 117, 131, 134, 136138, 141, 144, 146, 154, 155, 161 GCC 54, 55, 70, 83 GDI 167, 191
General Packet Radio System see GPRS Generic technologies 9, 68 GPRS 14, 2729, 31, 33, 303, 306, 316, 319, 322, 331, 332, 341, 392 Graphical user interface see GUI Graphics device interface see GDI Grid see Lists GT see Generic technologies GUI Drawing 24, 165, 166, 296, 303, 451, 456, 458, 472 Event handling 16, 165, 166, 272
Handle 1, 30, 36, 38, 73, 79, 84, 8688, 158, 172, 195, 207, 208, 252, 253, 270, 273, 288, 306, 311, 314, 321, 342, 346, 349, 364, 409 Heap 44, 8083, 85, 160 High-speed circuit-switched data see HSCSD host-name resolution 316 HSCSD 29, 138, 139 HTTP 27, 31, 69, 331, 333, 391, 392, 419 Hypertext transfer protocol see HTTP
IAP 28, 316, 319, 328 Icons 25, 55, 119, 215, 225, 226, 247, 258, 294, 298, 379 IDE 51, 58, 59, 70, 134, 141, 146 IMAP4 14, 27, 29, 318, 337, 379, 382, 385 IMC 30, 416 IMPORTC 72, 73, 75, 76 inf le 56 Information le (.inf) 55, 197
514
INDEX
Infrared data association FIR 325 IrCOMM 324, 326 IrLMP 324326, 333 IrMUX 29, 326, 355, 356 IrTinyP 326 SIR 325 Integrated development environment see IDE Integration testing 131, 136, 146 Interaction design 12, 15, 93, 96, 104, 106, 131 International Organization for Standardization see ISO Internationalization 9, 51, 433 Internet Access Point 28, 33, 316, 319 see also IAP Internet Mail Consortium see IMC Internet Service provider see ISP Interthread communication 78, 86, 189 see also ITC IrCOMM 324, 326, 345, 356 IrDA 2729, 34, 313, 315, 321, 324327, 349, 419, 489 see Infrared data association IrLMP 324326, 333 IrMUX 29, 326, 355 ISM 28, 329 ISO 94, 322 ISP 319 ITC 78, 86, 189 Iterative development 94, 133 ITU-T 22
Application Manager 442446, 488 archive le see JAR le CLDC 18, 52, 425, 427431, 434, 435, 438, 439, 441, 485 J2ME 52, 425427, 431, 448 JAD 445447 KVM 425, 427, 430 Midlet 429, 430, 438, 439, 441443, 445447, 449, 451, 452, 487, 489 MIDP 11, 14, 18, 51, 52, 332, 425, 427, 429, 435, 438441, 446, 447, 449, 455, 476, 483, 489 Virtual machine 54, 425, 427, 430, 431, 437 VM 426430, 434
K Virtual Machine see also KVM Kernel Kernel executive 79 Keypad Application launch-and-swap key 22 Clear key 493 Edit key 23, 112 End key 22 Numeric keys 22 Power key 493 Select key 111, 112 Send key 22 Softkey 120, 185, 206, 207, 213, 239, 240, 250, 253255, 265, 269, 304, 482 Voice key 493 KVM 425, 428, 430
J2ME 52, 425429, 432434, 438, 447 JAD 445447, 488, 489 JAR le 429, 445447 Java application descriptor see JAD
L2CAP 29, 329, 330, 351, 365 LAF 293296 LDD 313 Leavescan 141 Leaving 36, 44, 82, 83, 145, 179, 194, 300, 332
INDEX
515
Library 9, 10, 21, 24, 33, 40, 47, 51, 52, 56, 58, 62, 64, 7173, 77, 79, 89, 146, 157, 165, 179, 193, 293, 315, 318 see also DLLs, Shared Libraries (.dll) Licensee 10, 11, 13, 67, 68, 300 Link management protocol see LMP Linux 5 List box 16, 25, 221 see Lists Lists see also specic classes Icons 25, 119, 215, 225, 226, 247, 258, 294, 298, 379 List item string formatting 215 List layout 214, 216 Lists inside dialogs 223 Primary orientation 232 Subcells 232234 List types Grid 16, 25, 210, 228, 229, 261, 297 Markable list 212, 220, 225 Menu list 212, 220 Multiselection list 212, 220, 255, 263, 264 Selection list 25, 212, 220 Setting list 213, 266, 267, 270 Vertical list 214, 216, 220 LMP 330 Loc les (.loc) 185 Localization 9, 12, 51, 58, 65, 183, 247, 380 Logical device driver 313 see also LDD Logical link control and adaptation protocol see L2CAP Look and feel see LAF
M class 282, 289, 320 Mail see Messaging Main pane 16, 26, 180, 194, 209
Makele 58 makmake 55, 59 MAknBackgroundProcess StepL() function 253 MARM 343, 345 MCommsBaseClass 342 MDesCArray 210, 221, 235, 236, 238 MEikListBoxObserver 210 Memory management Allocation 44, 83, 139, 158, 237, 439 Heap 44, 83 Memory leaks 37, 44, 82, 92, 136 Memory pages 80, 335, 433, 493 see also Exceptions Stack 254, 263, 324, 325, 327, 332, 371 Menus 16, 22, 25, 58, 120, 181, 193, 239, 240, 269, 380 Message server 31, 38, 310, 311, 318, 320, 341, 374, 377, 378, 380, 381, 405 Message-type module see MTM Messaging Attachments 318, 385, 405 BIO message 30 Client-side MTM 318, 379 E-mail 27, 29, 106, 245, 318, 335, 375, 381385, 405 Fax 318, 341, 373, 375, 376 Message server 310, 311, 318, 320, 341, 342, 374, 376, 377, 381 MHTML 384 MTM 31, 310, 312, 318, 373, 376, 379381 MTM Registry 318, 380 mtmgen 380 Multimedia 17, 2729, 31, 32, 34, 106, 303, 341, 375, 377, 391393, 395, 405 Receiving mail 385 Send As API 401 Sending mail 382
516
INDEX
Messaging (continued ) SendUI 376, 380, 401, 403405 Server-side MTM 318, 380 Short message 17, 25, 27, 29, 34, 106, 213, 279, 312, 349, 375, 377, 386 Smart message 17, 30, 46, 395, 396, 398, 400 UI Data MTM 318, 379 UI MTM 318, 379 MHTML 384 Microkernel 5, 7, 9, 15, 35, 37, 38, 50, 71, 92, 309 MIDI 279, 283, 291, 483 Midlet 18, 407 see also Java MIDP 11, 14, 18, 51, 52, 332 see also Java MIME MIME recognizer 30, 64 MListBoxModel 210 MMdaAudioOutputStreamCallback 285 MMdaAudioPlayerCallback 285 MMdaAudioToneObserver 282 MMdaObjectStateChangeObserver 288, 289 MMP le 57 MMS 14, 2729, 3134, 106, 303, 306, 318, 332, 375, 382, 391393, 395 MMsgBioControl 399, 400 MMsvEntryObserver 381 MMsvSessionObserver 381, 390 Mobile information device prole see MIDP MObjectProvider 208 Model 9, 15, 28, 35, 3740, 47, 56, 71, 72, 298, 302, 303, 310, 322 see also MVC ModelViewController see MVC MProgressDialogCallback DialogDismissedL() function 253 MSendAsObserver 401 MSocketNotify 317
MTM 31, 310, 312, 318, 373, 376, 377, 379, 388 MTM Registry 318, 380 mtmgen 380, 381 Multi-bitmap format 54 Multimedia message service see MMS Multiprocess advanced risk or machine see MARM Multipurpose Internet mail extension see MIME Multitasking Cooperative 79, 87 Preemptive 79, 87 MVC 3840, 50, 210 Narrow-band socket 397 see also NBS Navigation pane 196, 198, 199, 201203, 269 NBS 397 see also narrow-band socket Networking Bluetooth 303, 306, 314, 315, 321, 329, 330, 334, 340, 341, 343, 356, 357, 361, 362, 364, 366, 395, 397, 413415 CSD 27, 316, 331, 392 GPRS 29, 303, 306, 316, 319, 322, 331, 332, 341, 392 GSM 29, 312, 328, 331, 332, 334, 372, 386 HSCSD 29, 138 IrDA 27, 313, 315, 321, 324327, 349, 350, 354, 355, 419 PPP 326, 328, 329, 333, 414 TCP/IP 27, 28, 315, 321, 327, 328, 332, 349351, 355, 415, 419 WAP 27, 34, 311, 315, 319, 332, 336, 349, 351, 371, 391393, 419421 WDP 332 WSP 333 NewL() function 169, 224, 227
INDEX
517
NifMan 316, 328, 329 Nokia 7650, 8, 9, 11, 23, 28, 113, 121, 293, 294, 298, 303, 313, 322, 343, 395, 409 Notications Conrmation note 245, 248 Error note 249, 277 Information note 247 Permanent note 249 Soft notication 254 Warning note 248 NSM 30 Numeric keys 22, 242
OBEX 27, 419, 420 Object exchange see OBEX Object Provider Mechanism 207, 208 Observer 15, 35, 37, 40, 42, 43, 48, 50, 71, 267, 271, 279, 282, 287, 321, 381 OCP 39 OCR 155 OOM see Exceptions, Out-of-memory Openclosed principle see OCP Open systems interconnection see OSI Optical character recognition see OCR OSI 310, 322, 333 OTA 449, 487, 489 Out-of-memory see Exceptions, Out-of-memory Over the air see OTA
Package descriptors 86 Package les 62 Palm OS 5, 67 Panes Battery pane 196, 204 Command button array 174, 206, 262, 274, 304, 450
Context pane 196198 Decorators 199, 202 Find pane 209 Full-screen mode 205 Idle layout 195, 196, 298 Indicator pane 195, 196 Main pane 16, 26, 180, 194, 209 Navigation pane 196, 198, 200203, 269 Normal layout 195 Signal pane 196, 203, 204 Status pane 16, 26, 174, 183, 194196, 198, 203206, 209, 294, 295, 297299 Title pane 196, 197 Universal indicator pane 204, 205, 209 Paper prototypes 96, 103105, 112, 116, 129, 130 PDD 313, 345 see also physical device driver PDI 30, 416 Pearl 10 Perl 55, 70 Personal data interchange see PDI Physical device driver 313 see also PDD pkg le 62 Plug-in modules 28, 29, 302, 309312, 315, 341, 375 Pocket PC 5 Point-to-point protocol 28, 323, 326 see also PPP POP3 14, 27, 29, 318, 337, 379, 381, 382, 385 Post Ofce Protocol 3 see POP3 Power key 493 PPP 28, 33, 326, 328, 329, 333, 337, 414 Preemptive multitasking 79, 87 Priorities 79, 281, 291, 299, 455 Process Priority 79, 88, 204, 281, 282, 286, 300, 416, 455
518
INDEX
Progress note 250, 251 Project le (.mmp) 71 Protocol Protocol module 10, 310314, 316, 317, 323, 324, 327, 348, 349 PRT 310 QiKON 108 Quartz 10, 334 Queries Conrmation query 121, 242, 255, 256, 258, 264 Data query 121, 256, 258260 Global query 255, 264 List query 121, 254, 261, 262 Local query 255 Multiselection list query 263 Setting views 265 RCall 372 RComm 343, 346, 347 RCommServ 314, 343, 349, 350 RDevComm 314 Receiving mail 385 Reference application 14, 21, 33 Requirements gathering 45 Resources Compiled resources les (.rsc) 66 epocrc 65 Generated resource les (.rsg) 185 Rcomp 65 Resource denition 184, 185, 223, 225, 246, 247, 298, 380 Resource les (.rss) 65 Resource header le (.rh) 66, 185, 186 RFCOMM 29, 329, 351, 363 RHostResolver 350, 354, 355 GetName() function 355 RLine 372 RNetDatabase 350, 355 RNif 351 RockPaperScissors game see RPS
RPhone 372 RPS 46, 56, 57, 60, 64, 7173, 78, 79, 81, 86, 90, 168, 171174, 177, 180182, 185, 188190, 193, 304, 342, 396 RS-232, 28, 311, 313, 314, 321, 323, 324, 326, 334, 343346 rsc le 65, 66 RServiceResolver 350 RSessionBase CreateSession() function 89 SendReceive() function 311 rsg le 66 rss le 6567 RSubsessionBase 311, 342 RTelServer 371, 372 RTTI 42 RWAPConn 371 RWAPServ 371 RWSPCLConn 371 RWSPCOConn 371
S60 7 Screen Full-screen mode 477, 481 SDK 12, 51, 52, 54, 55, 62, 63, 66, 70, 141, 407, 416 SDP 29, 329, 330 see also service discovery protocol Security 5, 7, 9, 12, 34, 330, 336338, 341, 356358, 361, 364, 366, 428430 Select key 111, 112, 120 Send As API 401 Send key 22, 493 Sending mail 382 SendUI 58, 376, 382, 401, 403, 404 Serial comms 311, 313, 314, 317, 323, 326 Serial protocol module 312, 313 Series 60 Platform 13, 6, 818, 21, 22, 24, 2631, 33, 34, 36, 44, 45, 48, 49, 51, 52, 61, 62, 65, 67, 68, 71, 93, 103, 118, 133, 165, 166, 174, 180, 182,
INDEX
519
183, 188, 193, 194, 207, 210, 211, 239, 255, 272, 277, 279, 291295, 297, 300, 302304, 306, 309, 318, 319, 321, 343, 349, 371, 374, 395, 405, 425, 428, 430, 449, 455, 489 Series 60 User Interface Style Guide 109 Server-side MTM 318 Servers Message server 9, 15, 31, 38, 71, 79, 86, 89, 310, 311, 318, 320, 374377, 381, 391 see also Clientserver framework Serial comms server 311, 314 Socket server 17, 38, 315, 316, 324, 326, 329, 341, 343, 349352, 356, 361 Telephony server 17, 38, 311, 317, 341, 343, 371, 374, 376 Window server 7, 165, 172, 189192 Service discovery protocol 29, 329, 330, 356, 357, 361, 364, 368 see also SDP Service resolution 316, 329, 330 see also Service discovery protocol Setting page 267271 Setting views Setting item 265267 Setting item list 265, 267 Setting page 267271 Short message service see SMS Short message service center see SMSC Simple mail transfer protocol see SMTP Sinewave tones 279, 281 SIR 325 SIS 12, 60, 6265, 380, 407 see also Symbian installation system Sisar 60, 62, 64, 65 Slow infrared see SIR
Smart messaging 174, 397 Smartphone 26, 1014, 17, 21, 22, 2628, 106108, 131, 139, 140, 142, 172, 209, 293, 322, 327, 343, 408, 409, 411, 412, 415, 416, 419 SMIL 393, 394 SMS 14, 25, 2831, 34, 106, 312, 349, 371, 375, 377, 382, 386388, 392, 395, 397 SMSC 386 SMTP 14, 27, 29, 31, 318, 335, 381, 382, 384, 385 Socket Socket server 311, 315, 316, 324, 329, 349, 350, 366 Soft notications 250, 254 Softkeys 22, 23, 26, 120, 174, 185, 206, 207, 209, 245, 255, 455 Software development kit see SDK SQL 319 Stack 14, 27, 29, 31, 33, 44, 45, 8083, 85, 89, 142, 152, 172, 180, 192, 199, 202, 203, 205, 254, 324, 332, 354, 371, 437 Standard Eikon 24, 166, 294 State pattern 43, 44, 48, 50 Static interface library 56 Status pane 16, 26, 174, 183, 194196, 198, 203206, 209, 294, 295, 297, 298 STP 69 Streams 56, 57, 171, 377, 432, 434, 487 Strings 10, 58, 84, 121, 183, 339 see also Descriptors Symbian community Semiconductor Partners 68 Symbian Competence Centers 7, 68 Symbian Training Partners 69 Technology Partners 68 Symbian Connect SDK 12, 51, 52 Symbian installation system 12, 380 see also SIS
520
INDEX
Symbian OS 1, 2, 415, 17, 21, 27, 28, 3033, 35, 3742, 44, 50, 52, 54, 56, 60, 6365, 6771, 78, 79, 8284, 87, 89, 92, 107, 140, 143, 146, 165, 166, 183, 197, 210, 272, 294, 295, 300, 301, 309, 313, 314, 319, 321, 328, 329, 333, 338, 340, 341, 343, 346, 354, 371, 374, 376, 380, 385, 395, 397, 401, 406412, 414, 416, 419 Synchronization 2, 17, 27, 29, 34, 323, 327, 385, 394, 406408, 410, 412, 413, 415422 Synchronized multimedia integration language see SMIL SyncML Device management 27, 327, 406, 420422 Synchronization 18, 27, 29, 34, 327, 414, 416, 418, 419 System testing 131, 132, 134, 135, 140
Tabs 108, 198202, 238, 264, 305 see also CAknTabGroup Target builds 55, 59, 89, 301 Target types ARM4 59 ARMI 59 THUMB 305 UDEB 147, 225 UREL 60 TBTSockAddr 350 TCommCaps 347 TCommCong 347 TCP/IP UDP 28, 29, 326, 327, 354 Telephony 317, 328, 329, 372, 373 see also ETel Telephony control module 310, 312, 317 Temporary window 26
Testing AppTest 154, 155 Black box testing 131, 144 Debugger 134, 135 EUnit 146 EUNITASSERT 149 EUNITDECLARETESTCASE TABLE 148 EUNITTESTCASE 147 EUnitdebugrunner 146, 147, 151, 152 Functional testing 117, 131, 134, 136138, 141, 144, 146, 154, 155, 161 Integration testing 131, 136, 146 Smoke testing 154, 160 Stress testing 141, 142, 161 System testing 131, 132, 134, 135, 140 Unit testing 131, 134, 136, 137, 139141, 144146, 151, 153155 Validation 36, 132, 133, 140, 141 Verication 131, 132, 140142, 146, 154, 155, 161, 339, 430 White box testing 131, 136, 139, 141, 144, 146 Thread Priority 79, 254, 281, 282, 284, 286 THUMB 56, 59, 305 TIrdaSockAddr 350, 355 Title pane 196, 197 TMdaAudioDataSettings 286, 287, 290 TMmsMsvEntry 377 TMsvEmailEntry 377, 382 TMsvEntry 377, 382, 388 TNameEntry 350 TNameRecord 350 TProtocolDesc 350 Trap harness TRAP 83 TRequestStatus 87, 264, 401 TSerialInfo 314, 349
INDEX
521
TSY 317, 328 TVwsViewId 273, 275, 276 UART 313 UCD 93, 95, 130 see also user-centered design UDP 28, 29, 326, 327, 354 UI see User interface UI Data MTM 318 UI MTM 318, 379, 380 UID 54, 5658, 62, 64, 168, 169, 273, 275, 300, 314, 361, 363, 377, 381, 397, 403 Uikon 16, 24, 39, 165168, 173, 182, 183, 185, 186, 193, 206, 294296 UIQ 10, 11, 106108, 302, 303 UML 35, 36, 46 Unique identier see UID Universal asynchronous receivertransmitter see UART Usability verication 16, 94, 96, 101, 114, 117, 121, 123, 129131 Use case 36, 46, 48, 101, 102, 117, 122, 492 User-centered design 93 see also UCD User datagram protocol see UDP User experience 12, 13, 17, 9396, 108, 114, 115, 130, 131 User interface see also GUI Style 10, 11, 16, 21, 24, 41, 51, 55, 104, 106, 108110, 114, 118, 166, 194, 212, 239, 294, 302, 304, 380, 470, 472 User modelling language see UML VC++, 51, 55 vCalendar 27, 30, 34, 395, 416, 419, 420 vCard 27, 30, 34, 395, 416, 417, 419, 420
View server 272, 277, 278 Views Activation 276, 277, 306 Deactivation 277 Parameterized views 276 Runtime behaviour 277 Transitions 274 View UID 275 Virtual machine 54, 427, 429 see also VM VM 54 see also Virtual machine vMail 416 Voice key 493 Wait note 245, 250, 252, 253 WAP 14, 27, 2931, 33, 34, 311, 322, 332, 336, 349, 351, 371, 391393, 487, 489 WAV 279, 283, 483 WDP 29, 332, 333, 371 White-box testing 131, 136, 139, 141, 144, 146 WINC 410, 412 Window Application Window 26, 194 Pop-up Window 25, 26 Temporary Window 26 Windows single process see WINS WINS 56, 58, 60, 78, 343, 345 Wireless application protocol see WAP Wireless datagram protocol see WDP Wireless markup language see WML Wireless session protocol see WSP wireless telephony application interface see WTAI WML 31, 395 WSP 27, 29, 333, 371, 391, 392, 419 WTAI 31 XML 393, 419