February, 2011 Business Card Application On Android Submitted by: Koren Shoval Eyal Segal Advisor: Nethanel Azuleus Index 1. INTRODUCTION ........................................................................................................................................................... 4 1.1. ABOUT ANDROID .................................................................................................................................................... 4 1.2. PROJECT GOALS ...................................................................................................................................................... 4 1.3. WORKING ENVIRONMENT ...................................................................................................................................... 5 2. SYSTEM OVERVIEW ..................................................................................................................................................... 6 2.1. TECHNOLOGIES ....................................................................................................................................................... 8 2.1.1. BLUETOOTH ........................................................................................................................................................ 8 2.1.2. ENCRYPTION ....................................................................................................................................................... 9 3. USE CASES ................................................................................................................................................................. 11 3.1. UC01 - BUSINESS CARD EDITOR ............................................................................................................................. 11 3.1.1. UC0101 - CREATE CARD ..................................................................................................................................... 11 3.1.2. UC0102 - EDIT CARD .......................................................................................................................................... 12 3.1.3. UC0103 - CREATE ITEM LAYOUT ........................................................................................................................ 12 3.1.4. UC0104 - EDIT ITEM LAYOUT ............................................................................................................................. 13 3.1.5. UC0105 - POSITION ITEM ON A CARD ............................................................................................................... 13 3.1.6. UC0106 - MANAGE ALL ITEMS ........................................................................................................................... 14 3.1.7. UC0107 - CREATE NEW THEME FROM A CARD .................................................................................................. 14 3.1.8. UC0108 - APPLY A THEME ................................................................................................................................. 15 3.1.9. UC0109 - SET BACKGROUND FROM ANDROID GALLERY .................................................................................... 15 3.2. UC02 – TABS BROWSE ........................................................................................................................................... 16 3.2.1. UC0201 - BROWSE FOR A CARD ........................................................................................................................ 16 3.2.2. UC0202 - SEARCH FOR A CARD .......................................................................................................................... 16 3.2.3. UC0203 - CREATE FOLDER ................................................................................................................................. 17 3.2.4. UC0204 - RENAME FOLDER ............................................................................................................................... 17 3.2.5. UC0205 - DELETE FOLDER .................................................................................................................................. 18 3.2.6. UC0206 - USE A BUSINESS CARD (SMS, CALL, EMAIL, ETC.). .............................................................................. 18 3.2.7. UC0207 - MOVE A CARD BETWEEN FOLDERS .................................................................................................... 19 3.3. UC03 – GALLERY BROWSER ................................................................................................................................... 20 3.3.1. UC0301 - BROWSE FOR A CARD ........................................................................................................................ 20 3.3.2. UC0302 - SEARCH FOR A CARD .......................................................................................................................... 21 3.3.3. UC0303 - CREATE FOLDER ................................................................................................................................. 22 3.3.4. UC0304 - RENAME FOLDER ............................................................................................................................... 22 3.3.5. UC0305 - DELETE FOLDER .................................................................................................................................. 23 3.3.6. UC0306 - USE A BUSINESS CARD (SMS, CALL, EMAIL, ETC.) ............................................................................... 23 3.3.7. UC0307 - MOVE A CARD BETWEEN FOLDERS .................................................................................................... 24 3.4. UC04 – BLUETOOTH .............................................................................................................................................. 25 3.4.1. UC0401 - SEND BUSINESS CARD VIA BLUETOOTH ............................................................................................. 25 3.4.2. UC0402 - RECEIVE A BUSINESS CARD ................................................................................................................ 27 4. DESIGN & IMPLEMENTATION .................................................................................................................................... 28 4.1. BACKGROUND SERVICE ......................................................................................................................................... 30 4.2. NOTIFICATIONS ..................................................................................................................................................... 32 4.3. STORAGE SERVICE ................................................................................................................................................. 34 4.4. BLUETOOTH & ENCRYPTION.................................................................................................................................. 35 4.4.1. SEND - RECEIVE SEQUENCE ............................................................................................................................... 38 4.4.2. ENCRYPTION SEQUENCE ................................................................................................................................... 39 4.5. BUSINESS CARDS DATA STRUCTURES .................................................................................................................... 41 4.6. BUSINESS CARD EDITOR ........................................................................................................................................ 43 4.7. BUSINESS CARDS TABS STYLE BROWSER ............................................................................................................... 45 4.8. BUSINESS CARDS GALLERY STYLE BROWSER ......................................................................................................... 47 5. OPTIMIZATIONS ........................................................................................................................................................ 49 6. REFERENCES .............................................................................................................................................................. 50 1. Introduction 1.1. About Android Android is an operating system, developed for mobile phones as open source code. The OS initially developed by Android Inc., which later was bought by Google in 2005. The Android is based on a modified version of Linux kernel, and provides a Java based libraries for application development. Today, there is a large community of developers which extends the Android devices abilities. Currently, there are over 200,000 applications available for Android. Android supports many known standards, including graphical abilities (OpenGL ES), database analysis (SQLite), data encryption and much more. In this project we used Android API level 8 (Version 2.2) 1.2. Project Goals One of our main goals in this project was to learn how to use Android API in order to develop an application for mobile phones. This includes understanding the way Android works in every aspect, and apply our knowledge with the Android SDK. Part of this main goal is to understand how a graphical user interface works in one device or how it fits into many different devices, and to build such a GUI. Another important goal is to successfully transmit data from one device to another, using Bluetooth protocol. The transmission consists of pairing two devices, connecting them and sending/receiving the data. The last goal was to make sure that the data can be transferred safe, according to user choice, using encryption protocol. This includes authentication process between two users who want to exchange data. To implement all these goals, we selected an application that manages business cards collection and allows transferring them between users with or without authentication. 1.3. Working Environment The OS we worked with is Windows Vista x86. Our development tools included the Eclipse IDE for Java, the Android SDK and emulators, Eclipse Memory Analyzer and two HTC mobile devices. For developing, building and debugging Android code, we used Eclipse IDE for Java and Android ADT for eclipse. At first, in order to simulate Android mobile phones, we used Android emulators which gave us the option to develop and debug on PC. Most of the development effort and testing was made on the HTC devices, since the emulators do not support bluetooth at this point. After the application was ready, we used Eclipse Memory Analyzer in order to examine our memory usage. 2. System Overview This application is for managing business cards collection. It consists of your own personal designed cards and received cards from your colleagues. You can design a business card, use pictures from the gallery as background, add your preferred details to the card and customize its layout, font and color. Main screen Editing a card The application offers several themes that can be applied to your new card. You can also create a theme from any card, and later apply it to other cards. In this application, you can manage your cards in two different ways – the gallery browser or the tabs browser, that provide different ways of cards presentation. In both ways, you can manage your folders, create new ones, rename and delete existing ones, and do the same with your cards. Browsing by tabs Cards as icons As for your cards, if a card has the relevant details, you can use it to call the phone number on the card, send SMS or Email, and send the card to your colleagues using Bluetooth. The data can be encrypted and authenticated, according to your choice. Another interesting option is to automatically generate cards for your contacts list. Each contact in the phone would have its own card with the contact details. A card can be sent via Bluetooth by selecting a card and a remove device to send it to. The transmission takes place in the background and the user is able to view the progress through Android’s notification bar. When the card arrives at the receiver, the card is displayed and can be accepted or declined. Select a device Receiving in progress… Save Card? 2.1. Technologies 2.1.1. Bluetooth Bluetooth is a proprietary open wireless technology standard for exchanging data over short distances. The Bluetooth specifications are developed and licensed by the Bluetooth Special Interest Group (SIG), which consists of more than 13,000 companies all over the world. There are many advantages of using Bluetooth as a data transfer method. Among them is low power consumption, which is one of the most problematic issues in the mobile phones world, high data throughput and high communication distance (depends on Bluetooth hardware). Android API Level 8 (version 2.2) supports Bluetooth 2.1 . Its throughput is about 1.4Mbit/sec and its maximum distance can reach 100 meters (class 1). To enable Bluetooth usage, Android uses two main protocols: SDP – service discovery protocol: Used to allow devices to discover what services each other support, and what parameters to use to connect to them. For example, when connecting a mobile phone to a Bluetooth headset, SDP will be used to determine which Bluetooth profiles are supported by the headset (headset profile, hands free profile, advanced audio distribution profile, etc.) and the protocol multiplexor settings needed to connect to each of them. Each service is identified by a Universally Unique Identifier (UUID), with official services (Bluetooth profiles) assigned a short form UUID (16 bits rather than the full 128) RFCOMM – Radio frequency communication: The RFCOMM protocol is a simple set of transport protocols, made on top of the L2CAP protocol, providing emulated RS-232 serial ports (up to sixty simultaneous connections to a Bluetooth device at a time). The protocol is based on the ETSI standard TS 07.10. RFCOMM is sometimes called serial port emulation. The Bluetooth serial port profile is based on this protocol. RFCOMM provides a simple reliable data stream to the user, similar to TCP. It is used directly by many telephony related profiles as a carrier for AT commands, as well as being a transport layer for OBEX over Bluetooth. Many Bluetooth applications use RFCOMM because of its widespread support and publicly available API on most operating systems. Additionally, applications that used a serial port to communicate can be quickly ported to use RFCOMM. With the Bluetooth API, a user can scan for other Bluetooth devices, connect or pair with them, query for paired Bluetooth devices, establish RFCOMM channels/sockets, connect to a specified socket on a remote device or transfer data to and from it. 2.1.2. Encryption The Java security APIs spans a wide range of areas. Cryptographic and public key infrastructure (PKI) interfaces provide the underlying basis for developing secure applications. Interfaces for performing authentication and access control enable applications to guard against unauthorized access to protected resources. The APIs allow for multiple interoperable implementations of algorithms and other security services. Services are implemented in providers, which are plugged into the Java platform via a standard interface that makes it easy for applications to obtain security services without having to know anything about their implementations. This allows developers to focus on how to integrate security into their applications, rather than on how to actually implement complex security mechanisms. The Java platform includes a number of providers that implement a core set of security services. It also allows for additional custom providers to be installed. This enables developers to extend the platform with new security mechanisms. The Java cryptography architecture is a framework for accessing and developing cryptographic functionality for the Java platform. It includes APIs for a large variety of cryptographic services, including: Message digest algorithms Digital signature algorithms Symmetric bulk encryption Symmetric stream encryption Asymmetric encryption Password-based encryption (PBE) Elliptic Curve Cryptography (ECC) Key agreement algorithms Key generators Message Authentication Codes (MACs) (Pseudo-)random number generators The Java platform includes built-in providers for many of the most commonly used cryptographic algorithms, including the RSA and DSA signature algorithms, the DES, AES, and ARCFOUR encryption algorithms, the MD5 and SHA-1 message digest algorithms, and the Diffie-Hellman key agreement algorithm. These default providers implement cryptographic algorithms in Java code. EKE – Encrypted Key Exchange Encrypted Key Exchange (also known as EKE) is a family of password-authenticated key agreement methods described by Steven M. Bellovin and Michael Merritt. Although several of the forms of EKE in this paper were later found to be flawed, the surviving, refined, and enhanced forms of EKE effectively make this the first method to amplify a shared password into a shared key, where the shared key may subsequently be used to provide a zero-knowledge password proof or other functions. In the most general form of EKE, at least one party encrypts an ephemeral (one-time) public key using a password, and sends it to a second party, who decrypts it and uses it to negotiate a shared key with the first party. A second paper describes Augmented-EKE, and introduced the concept of augmented passwordauthenticated key agreement for client/server scenarios. Augmented methods have the added goal of ensuring that password verification data stolen from a server cannot be used by an attacker to masquerade as the client, unless the attacker first determines the password (e.g. by performing a brute force attack on the stolen data). A version of EKE based on Diffie-Hellman, known as DH-EKE, has survived attack and has led to improved variations, such as the PAKfamily of methods in IEEE P1363.2. 3. Use Cases In the following section we will describe the use cases for the application according to the project goals and usage scenarios. These will later be used in the application design. 3.1. UC01 - Business Card Editor These use cases describe usage scenarios for the business card editor activity. 3.1.1. UC0101 - Create card This use case describes creation of a new business card. It is triggered by starting the card editor from the main screen. - Main scenario 1. User starts card editor (from main) 2. A card is generated using the default theme 3. A popup screen opens and lets user edit item values 4. User edits default items and clicks “save” 5. The popup closes showing the editor surface 6. The user clicks on menu option “save as” and saves the card 7. A save dialog opens and the user selects where to save the card and its filename 8. Users clicks “ok” and the card is saved - Exceptions 4. User clicks “cancel” or presses the back button in the popup screen and the changes are ignored. 8. User clicks “cancel” in save dialog 3.1.2. UC0102 - Edit card This use case describes editing of an existing card. It is triggered from main screen. - Main scenario 1. User starts cards browser 2. User selects the wanted folder 3. User browse for the card to edit 4. User clicks on menu option “Edit” 5. The editor opens with the selected card 3.1.3. UC0103 - Create item layout This use case describes creation of new business card item when creating or editing a card. It is triggered by the user at the editor surface screen. - Main Scenario 1. User clicks on menu option “Add Item” 2. Layout dialog opens with the item’s information 3. User edits item’s text content 4. User updates item’s type, style and color 5. User clicks on “ok” button to save the changes 6. Editor gets back the updated item, save the changes to the card and updates the surface - Exceptions 6. User clicks “cancel” or presses the back button in the dialog screen and the changes are ignored. 3.1.4. UC0104 - Edit item layout This use case describes how to edit a business card item that is already on the card’s surface. It is triggered by the user at the editor surface. - Main Scenario 1. User clicks on surface where the item’s bounding box should be 2. The top item with a bounding box that contains the clicked position will be selected and several options will show on the side of the item (delete, edit, move) 3. User clicks on the “edit” option 4. Layout dialog opens with the item’s information 5. User edits item’s text content 6. User updates item’s type, style and color 7. User clicks on “ok” button to save the changes 8. Editor gets back the updated item, save the changes to the card and updates the surface - Exceptions 7. User clicks “cancel” or presses the back button in the dialog screen and the changes are ignored. 3.1.5. UC0105 - Position item on a card This use case describes how to move a business card item on the surface of the card. It is triggered by the user and starts at the editor surface. - Main Scenario 1. User clicks on an item 2. Editor surface shows edit, remove and drag buttons and a frame around the item 3. The user presses on the surface inside the frame or on the drag button and drags the item on the surface to its new position 4. The editor surface saves the changes to the card - Exceptions 2. User clicks outside of the item’s frame to cancel the item’s selection. 3.1.6. UC0106 - Manage all items This use case describes how to edit all of the business card items at once. It is triggered by the user and starts at the editor surface. - Main Scenario 1. User clicks on menu option “Items” 2. Items dialog opens with a list the card’s items 3. User edits each item’s value and selects “Save” 4. The editor surface saves the changes to the card - Exceptions 3. User clicks back or “Cancel” and the changes are discarded 3.1.7. UC0107 - Create new theme from a card This use case describes creating a new theme based on an existing card. It is triggered from editor surface. - Main Scenario 1. User clicks menu option “save as theme” 2. A “save as…” dialog pops up 3. User enters the name of the new theme and presses “ok”. 4. The theme is saved to storage - Exceptions 4. User clicks on “Cancel. The theme is not created 3.1.8. UC0108 - Apply a theme This use case describes how to apply a theme on a business card. It is triggered by the user and starts at the editor surface. - Main Scenario 1. User clicks on menu option “Set Theme” 2. A themes gallery popup with the first theme applied to the card. 3. User swipes left or right to iterate between themes, each swipe alters the layout of the card according to the current theme. 4. User clicks on “Select theme” and the theme is set on the card 5. Editor gets the result back from the themes gallery and set the updates business card on the surface. - Exceptions 4. User clicks the back button and the changes are ignored. 3.1.9. UC0109 - Set background from android gallery This use case describes setup of card background, which is chosen from phone gallery. It is triggered from editor surface. - Main Scenario 1. User clicks on menu option “Set background” 2. The phone gallery opens 3. User clicks on the wanted picture 4. The editor surface returns, and the selected picture is set as background 3.2. UC02 – Tabs Browse These use cases describe usage scenarios for the business card tabs browser activity. 3.2.1. UC0201 - Browse for a card This use case describes how to locate a business card inside the tabs browser. It is triggered by the user and starts at the main activity. - Main Scenario 1. User clicks on “browse” button at main. 2. Browse activity opens up to show the default search tab 3. User selects the folder with the card by clicking the folder’s tab 4. The tabs view updates the list of cards to display the cards in the current folder 5. User scrolls to the requested card and clicks on the card to select it 3.2.2. UC0202 - Search for a card This use case describes how to locate a business card inside the tabs browser. It is triggered by the user and starts at the browser’s default tab. - Main Scenario 1. User clicks on “Search” tab 2. Browse activity moves to the Search tab and shows all available cards 3. User clicks on the search text box and the keyboard appears 4. User writes a set of characters or words to find 5. Browse activity hides cards that do not contain the search text 6. User scrolls to the requested card and clicks on the card to select it 3.2.3. UC0203 - Create folder This use case describes creation of a new folder. It is triggered from tabs browser screen. - Main Scenario 1. User clicks the “New…” tab or chooses menu option “Create folder” 2. An input dialog pops up 3. User inserts the new folder name and clicks “Ok” button 4. The folder is created and appears as a tab - Exceptions 3. User clicks the back button or “Cancel” button and the folder is not created. 3. User enters an existing name. The current tab is changed to the existing tab, and no new folder is created 3. User enters a forbidden name (“New…”, “Contacts”, “Search”). No folder is created and the last used tab is active again 3.2.4. UC0204 - Rename folder This use case describes renaming of an existing folder. It is triggered from tabs browser screen. - Main Scenario 1. User selects the folder he want to rename 2. User clicks on menu option “Rename folder” while no card is selected 3. An input dialog pops up 4. User inserts the new folder name and clicks “Ok” button 5. The folder is renamed and appears as a tab with the new name - Exceptions 4. User clicks the back button or “Cancel” button and the folder is not renamed. 3.2.5. UC0205 - Delete folder This use case describes how to remove a business card using the tabs browser. It is triggered by the user and starts at tabs browse activity - Main Scenario 1. User selects a specific folder by clicking its tab 2. User chooses menu option “Delete folder” 3. A confirmation dialog pops up 4. User clicks “Ok” button and the folder is deleted - Exceptions 4. User clicks the back button or “Cancel” button and the folder is not deleted. 3.2.6. UC0206 - Use a business card (SMS, Call, Email, etc.). This use case describes usage of a business card, in order to call existing phone number, send Email or SMS, and send via bluetooth. It is triggered from tabs browser screen - Main Scenario 1. User selects a specific folder by clicking its tab 2. User searches the wanted card in the list 3. User selects the card 4. User clicks on menu button and chooses the wanted action from the enabled actions 3.2.7. UC0207 - Move a card between folders This use case describes how to move a business card from one folder to another using the tabs browser. It is triggered by the user and starts at tabs browse activity - Main Scenario 5. User selects the specific card 6. User chooses menu option “Move” 7. A folder selection dialog pops up 8. User selects the folder to move the card to and clicks “Ok” 9. The card is moved to the selected tab and the Browser sets that tab as the current view - Exceptions 5. User clicks the back button or “Cancel” button and the user returns to the current tab. 3.3. UC03 – Gallery Browser These use cases describe usage scenarios for the business card gallery browser activity. 3.3.1. UC0301 - Browse for a card This use case describes browsing a card within the gallery browser. It is triggered from main screen. - Main Scenario 1. User clicks on “browse” button at main 2. Browse activity opens up to show the first folder in the gallery 3. User finds and clicks the folder with the card by swiping the folders 4. A list of cards in the selected folder is shown 5. User swipes on the cards in order to browse the wanted card - Branch 3b. User flips up the view 3b.1 Explorer view is opened with all of the folders as little icons 3b.2 User clicks on the wanted folder 3b.3 Continue to step 4 5b. User flips up the view 5b.1 Explorer view is opened with all of the cards as little icons 5b.2 User clicks on the wanted card 5b.3 The card is shown on full screen 3.3.2. UC0302 - Search for a card This use case describes how to locate a business card inside the gallery browser. It is triggered by the user and starts at the browser’s first screen. - Main Scenario 1. Browse activity opens up to show the first folder in the gallery 2. The user swipes down the screen and the search line appears 3. The user clicks on the search line and the keyboard appears 4. The user writes down the string sequence he wants to search for 5. All the cards with an item that contains such string will appear as list - Branch 2b. If the user wants to search inside specific folder 2b.1 User swipes to a specific folder and clicks it 2b.2 The user swipes down the screen and the search line appears 2b.3 Continue to step 3 2b.1b. User flips up the view 1b.1 Explorer view is opened with all of the folders as little icons 1b.2 User clicks on the wanted folder he wants to search in 1b.3 Continue to step 2b.2 3.3.3. UC0303 - Create folder This use case describes creation of a new folder. It is triggered from gallery browser screen. - Main Scenario 1. User clicks on menu option “Create folder" within the folders view 2. An input dialog pops up 3. User inserts the new folder name and clicks “Ok” button 4. The folder is created - Exceptions 3. User clicks the back button or “Cancel” button and the folder is not created 3. User enters an existing name. No new folder is created 3. User enters a forbidden name (“New…”, “Contacts”, “Search”). No folder is created 3.3.4. UC0304 - Rename folder This use case describes renaming of an existing folder. It is triggered from gallery browser screen. - Main Scenario 1. User swipes the folders and selects the folder he want to rename 2. User clicks on menu option “Rename folder” 3. An input dialog pops up 4. User inserts the new folder name and clicks “Ok” button 5. The folder is renamed - Exceptions 4. User clicks the back button or “Cancel” button and the folder is not renamed. 3.3.5. UC0305 - Delete folder This use case describes how to remove a business card. It is triggered by the user and starts at gallery browser. - Main Scenario 1. User selects a specific folder by swiping the folders 2. User chooses menu option “Delete folder” 3. A confirmation dialog pops up 4. User clicks “Ok” button and the folder is deleted - Exceptions 4. User clicks the back button or “Cancel” button and the folder is not deleted. 3.3.6. UC0306 - Use a business card (SMS, Call, Email, etc.) This use case describes usage of a business card, in order to call existing phone number, send Email or SMS, and send via Bluetooth. It is triggered from gallery browser screen. - Main Scenario 1. User selects a specific folder by swiping the folders and clicks the folder 2. User searches the wanted card in the list by swiping the cards 3. User clicks on menu button and chooses the wanted action from the enabled actions - Branch 1b. User flips up the view 1b.1 Explorer view is opened with all of the folders as little icons 1b.2 User clicks on the wanted folder he wants to enter 1b.3 Continue to step 2 3.3.7. UC0307 - Move a card between folders This use case describes how to move a business card from one folder to another using the gallery browser. It is triggered by the user and starts at the gallery browser. - Main Scenario 1. User selects a specific folder by swiping the folders and clicks the folder 2. User searches the wanted card in the list by swiping the cards 3. User chooses menu option “Move” 4. A folder selection dialog pops up 5. User selects the folder to move the card to and clicks “Ok” 6. The card is moved to the selected folder - Branch 1b. User flips up the view 1b.1 Explorer view is opened with all of the folders as little icons 1b.2 User clicks on the wanted folder he wants to enter 1b.3 Continue to step 2 2b. User flips up the view 2b.1 Explorer view is opened with all of the cards in the folder as little icons 2b.2 User clicks on the wanted card 2b.3 Continue to step 3 - Exceptions 5. User clicks the back button or “Cancel” button and the user returns to the current tab. 3.4. UC04 – Bluetooth These use cases describe usage scenarios for sending and receiving business cards via Bluetooth. 3.4.1. UC0401 - Send business card via Bluetooth Starts at browser with a selected card - Main Scenario 1. User clicks on menu option "Send” 2. Device picker opens up with a list of paired devices 3. User clicks on a device 4. Connection is made with the device 5. The card is sent to the remote device 6. Application waits for a status response 7. Application displays the status to the user - Branch 3. If the device is not in the known device list 3b.1 User clicks on “Scan for new devices” 3b.2 Application request device detection 3b.3 Each detected device is added to the list 3b.4 User clicks on a device 3b.5 Continue to step 4 5b. If encryption is enabled 5b.1 Application asks user for a password 5b.2 User inserts an agreed upon password and clicks “ok” 5b.3 Application starts the EKE protocol to agree on a secret key 5b.4 Application sends an encrypted card using the key 5b.5 Continue to step 6 - Exceptions 1. If bluetooth is not enabled ask user to enable bluetooth 1.1 If user clicks “cancel” the operation is canceled and the application return to the browser view 4. Connection to remote device fails 4.1 Display error message 5b.3 Authentication fails 5b.3.1 Display error message and abort operation 6. Read timeout exception 6.1 Display unknown response message 3.4.2. UC0402 - Receive a business card Service listens for an incoming connection - Main Scenario 1. A remote device a connection is accepted 2. Service forks the socket to a receive handler 3. Receiver reads the data from the remote device 4. Receiver notifies the user about an incoming card 5. Receiver saves the card to the default “received” folder 6. Receiver sends the status (Accepted, Refused, Failed) to the remote device - Branch 4b. If the message is encrypted 3b.4 Receiver opens a password dialog 3b.5 User inserts a password and clicks on “ok” 3b.6 Receiver start the EKE protocol 3b.7 Receiver reads encrypted data from the remote device 3b. If the preference for “confirmation dialog” is checked 2b.4 Receiver open a save card dialog, showing the card 2b.5 User selects the location to save and clicks “ok” 2b.6 Receiver saves the card to that location 2b.7 Continue with step 6 - Exceptions 1. If bluetooth is not enabled then nothing will happen 3. Read timeout exception 3.1 Display error message 3b.3 Authentication fails 3b.3.1 Display error message and abort operation 4. Design & Implementation This project was designed in 3 layers - Android SDK Layer, Framework Layer and Business Card Application Layer. Each layer is built on top of the previous layer, adding more functionality to the next one. The Framework layer contains most of the code and is completely disconnected from the business card aspect of the project. In the following sections we will describe the large components that make up this layer. Drawing 4.1 – Framework layer components in general The Business Cards Application layer contains several UI components that are specific to editing and managing business cards. It contains the logic concerning business cards structural data and utilities for painting, importing Android contacts and business card theme management. Drawing 4.2 – Business Cards Application layer components in general 4.1. Background Service “A Service is an application component representing either an application's desire to perform a longerrunning operation while not interacting with the user or to supply functionality for other applications to use.” - Android docs Our Background service runs as part of the application’s process (default behavior) in a separate thread. It starts when the phone is started or when the application is opened. It handles incoming and outgoing bluetooth messages using our bluetooth implementation. The service allows for an application to register a message type to be handled either by a handler class or an answer activity. The Business cards application registers a message of type “business card” in the service to be handled either by an business card answer activity or by a batch handler (according to the preferences set by the user). The service can also accept requests from activities in the application to send a message via bluetooth to a specified device address. The bluetooth messaging sequences will be explained in the bluetooth section later on. The background service also uses the notification component to alert the user about changes in the application such as “service started”, “bluetooth not available”, “incoming message”, etc. In the following class diagram, you can see the “LocalService” which is the name of the class representing the background service. In is started by a boot completed receiver which is an Android broadcast receiver. An Android broadcast receiver is a class that listens to intents moving around the system. Each receiver filters the intents it wants to accept by specifying an action to filter by. That way the receiver wakes up only when an intent with that specific action is sent by another activity. The boot completed receiver listens to a boot action only and wakes up accordingly. As described above, the Registration block manages registration for message types and returns an IRunnableBlock to handle the incoming message type data. Here is a sample of code that registers a message type for an IRunnableBlock. if (ask_confimation == true) { LocalService.RegisterMessageTypeFor(Constants.BUSINESS_CARD_TYPE, RegisterationBlock.getAnswerActivityBlock(BusinessCardAnswerActivity.class)); } else { LocalService.RegisterMessageTypeFor(Constants.BUSINESS_CARD_TYPE, RegisterationBlock.getRunnableBlock(BusinessCardRunnableBlock.class)); } Drawing 4.1.1 – registering a runnable block for a message type code snippet The Bluetooth package represents the logic that manages bluetooth communication. The service uses this package to spawn new senders when a request to send a message arrives and to keep a listener alive in order to accept incoming bluetooth connections. class localserv ice Notification Serv ice Bluetooth Package «use» getRegistrationBlock() new Sender() new Listener() Service LocalServ ice BroadcastReceiver BootCompletedReceiv er + + + + + + + + + + Start() onReceive(Context, Intent) : void getService() : LocalService start(Context) : void stop(Context) : void RegisterMessageTypeFor(String, RegisterationBlock) : void getRegistredBlockFor(String) : RegisterationBlock onBind(Intent) : IBinder onStartCommand(Intent, int, int) : int onCreate() : void onDestroy() : void RegisterationBlock «interface» RegisterationBlock::IRunnableBlock + + + AnswerActivityClass: Class<?> BlockType: EnumBlockType + + getAnswerActivityBlock(Class<?>) : RegisterationBlock getRunnableBlock(Class<?>) : RegisterationBlock handleMessage(MessageBlock) : void Drawing 4.1.2 – background service class diagram +BlockType «enumeration» RegisterationBlock:: EnumBlockType «enum» AnswerActivity Runnable 4.2. Notifications Android provides a way to interact with the user without blocking the current work, using it’s notification mechanism. Each notification is an alert the shows up on the top panel of the screen. An application can post, remove and update notifications as needed. We added an abstraction over the basic android code that gives us the ability to keep the state of each notification in its own class and change its layout and text as needed. In the following class diagram you can see the notification service which is the notifications provider. The service is a singleton and supplies activities with new notificators by returning one of the implemented notificator objects (Notificator, ProgressBarNotificator). The common one is the notificator that supports updating and canceling the notification, setting a title and a description. A notificator can also accept a callback object which will be activated when the user click on the notification. This allows for interacting with the user while waiting for a response (usually with a timeout). class localserv ice NotificationServ ice -m_service «interface» INotificationService + + + + + + + + + + + + + + + + + + + getNotificator(String, String) : INotificator getNotificator() : INotificator getProgressBarNotificator(String) : ProgressBarNotificator notify(int, Notification) : void notify(int, String, String) : void notify(int, String, String, Class<?>, Bundle, INotificationCallback) : void getLocalNotificator() : INotificator cancel(int) : void -m_service getInstance() : INotificationService start(Context, String) : void stop() : void getLocalNotificator() : INotificator getNotificator(String, String) : INotificator getProgressBarNotificator(String) : ProgressBarNotificator getNotificator() : INotificator notify(int, String, String) : void notify(int, String, String, Class<?>, Bundle, INotificationCallback) : void notify(int, Notification) : void cancel(int) : void -m_service -m_notificator Notificator ProgressBarNotificator + + + ProgressBarNotificator(Context, INotificationService, int, String) notify(int) : void cancel() : void + + + + + + + + + Notificator(INotificationService, int) Notificator(INotificationService, int, String, String) setTitle(String) : void setDescription(String) : void notify(String, String) : void notify(String) : void notify(String, String, Class<?>, Bundle, INotificationCallback) : void notify(String, Class<?>, Bundle, INotificationCallback) : void cancel() : void «interface» INotificator + + + + + + + notify(String, String, Class<?>, Bundle, INotificationCallback) : void notify(String, Class<?>, Bundle, INotificationCallback) : void notify(String, String) : void notify(String) : void cancel() : void setTitle(String) : void setDescription(String) : void «use» «interface» INotificationCallback + Drawing 4.2.1 – notification service class diagram onActivityResult(Intent) : void The following code snippet shows how to create a notificator and add a notification to the alerts panel on the screen. INotificator notificator = NotificationService.getInstance().getNotificator(); // send a notification notificator.notify("What's up..."); // send an update notificator.notify("goodbye!"); // remove the notification notificator.cancel(); Drawing 4.2.2 – notifications code snippet 4.3. Storage Service Android provides several options for persistency. It has internal storage visible only to the application and external storage which is basically the SD-Card and SQLite databases. In our design we added an abstraction over the storage type and automatically selected the external as default or the internal storage if an SD-Card is missing. We used a strategy pattern for selecting a storage adapter. There are several adapter types and a decorator cache adapter that can be used over the internal and external adapters. The usage model is to first configure several adapters and access each using a key. For example, using the key “images” will access an adapter which is directed to “images” directory. Same applies with “cards”, “themes” or every other directory. This gives us the ability to use different directories without the need to change the application accordingly. In the following class diagram you can see the singleton storage service that allows adding new adapters. The service uses the StorageFactory which is a simple factory pattern that we use to abstract access to the actual class created. The null storage adapter is used when both the external and internal adapters fail to instantiate. The storage service also provides two storage tools, the temporary storage that allows caching data and the image storage that eases loading of resources. class storage StorageServ ice «enumeration» StorageAdapterFactory:: StorageType + + + + + + + «enum» Internal SdCard ImageStorage start(Context, String) : void getAdapter(String) : IStorageAdapter setAdapter(String, String, boolean) : IStorageAdapter setAdapter(String, IStorageAdapter) : void combinePath(String, String) : String getImageStorage() : ImageStorage getTemporaryStorage() : TemporaryStorage + + + + + + ImageStorage(Context) getBitmap(int) : Bitmap getDrawable(int) : BitmapDrawable unpackBitmap(byte[]) : Bitmap packBitmap(Bitmap) : byte[] asDrawable(Bitmap) : BitmapDrawable TemporaryStorage + + + + «use» TemporaryStorage(Context) read(String) : Object remove(String) : void cache(Serializable) : String InternalStorageAdapter StorageAdapterFactory + + getAdapter(Context, String, StorageType, boolean) : IStorageAdapter «interface» IStorageAdapter + + + + + + + + + + + + + getPath() : String read(String, String) : Object write(Serializable, String, String) : void delete(String, String) : void getItems(String, Filter) : String[] getFile(String, String) : File readBitmap(String, String) : Bitmap writeBitmap(Bitmap, String, String) : void createFolder(String, String) : void deleteFolder(String, String) : void moveFolder(String, String, String, String) : void move(String, String, String, String) : void ~m_adapter setDefaultFolders(String[]) : void InternalStorageAdapter(Context, String) StorageAdapter + + + + + + + + + + + + + + + + StorageAdapter(String) getPath() : String read(String, String) : Object write(Serializable, String, String) : void delete(String, String) : void move(String, String, String, String) : void getItems(String, Filter) : String[] getFile(String, String) : File readBitmap(String, String) : Bitmap writeBitmap(Bitmap, String, String) : void createFolder(String, String) : void deleteFolder(String, String) : void moveFolder(String, String, String, String) : void combinePath(String, String) : String makeSureExists(String) : void setDefaultFolders(String[]) : void SdCardStorageAdapter + + + SdCardStorageAdapter(String) isWriteable() : boolean isReadable() : boolean NullStorageAdapter «use» StorageCache +All «enumeration» IStorageAdapter::Filter::EnumFilter «enum» Directories Files All IStorageAdapter::Filter + + + +Directories +Files Directories: Filter = new Filter(Enum... {readOnly} Files: Filter = new Filter(Enum... {readOnly} All: Filter = new Filter(Enum... {readOnly} + + + setIncludeVirtual() : Filter equals(Object) : boolean includeVirtual() : boolean + + + + + + + + + + + + + + StorageCache(IStorageAdapter) getPath() : String read(String, String) : Object write(Serializable, String, String) : void delete(String, String) : void move(String, String, String, String) : void getItems(String, Filter) : String[] readBitmap(String, String) : Bitmap writeBitmap(Bitmap, String, String) : void getFile(String, String) : File createFolder(String, String) : void deleteFolder(String, String) : void moveFolder(String, String, String, String) : void setDefaultFolders(String[]) : void Drawing 4.3.1 – storage service class diagram + + + + + + + + NullStorageAdapter(String) read(String, String) : Object write(Serializable, String, String) : void delete(String, String) : void getItems(String, Filter) : String[] getFile(String, String) : File readBitmap(String, String) : Bitmap writeBitmap(Bitmap, String, String) : void 4.4. Bluetooth & Encryption In Android 2.2 Bluetooth is supported, therefore there is a built-in API for creating Bluetooth connections and using them for data transmission. That includes an automatic pairing action while trying to connect to an unpaired remote device. As a result, the developer has to perform few actions in order to use Bluetooth: connect or accept, depends if he is the server side or the client side, and after connection is established use the read and write methods. This is an example of how is it done: // *********** on the receiving side *********** // // create a new listening server socket BluetoothServerSocket server = adapter.listenUsingRfcommWithServiceRecord("btdevicename", "myid"); // wait for incoming connection BluetoothSocket socket = socket.accept(); // *********** on the sending side *********** // // create socket BluetoothSocket socket = bluetoothAdapter.getRemoteDevice(deviceAddress) .createRfcommSocketToServiceRecord(UUIDString); // try to connect socket.connect(); // *********** on both sides *********** // // get input & output stream InputStream in = socket.getInputStream(); OutputStream out = socket.getOutputStream(); // read bytes into buffer - blocking in.read(buffer); // do something with the data... // send bytes to client out.write(buffer); // close the client socket.close(); Drawing 4.4.1 – Bluetooth code snippet In our design, we use one listening thread, which listens to incoming connections for our application, and an additional thread for each card transfer – sending thread or receiving thread, depends on what side you are. In general a UI thread should not be used to perform IO operations since these are blocking calls. Moreover, in order to support multiple transmissions in and out, we use a different thread for each transmission. These threads are created in the background service either by an incoming connection or by an activity’s send request. The listening thread is started when the background service is started and waits for connections. When the user chooses to send a business card, a request (using Android broadcast capabilities) is sent to the background service with a reference to the card we want to send. The background service creates and starts a sending thread, which is responsible for connecting to the remote device. After the connection is established, the send thread sends the data block by block. On the receiving side, the listening thread accepts the connection and starts a receiving thread with the accepted socket, which handles the incoming blocks. After the listening thread creates the receiving thread, it continues to listen for other connections. This gives us the ability to send multiple cards without waiting for each transfer to be done. In order to avoid deadlocks, while a thread waits for incoming blocks and no data is arrived, we built a watchdog component. The watchdog is a thread which receives a timeout parameter and a callback. When the timeout is over it triggers the callback. The watchdog can be stopped, reset, and started again to allow reuse of the same instance. Each of the bluetooth threads start the watchdog when they perform blocking operations such as read, write and connect. Our implementation for the callback is to close the socket and cause an exception on the bluetooth thread which stops the blocking operation and handles the exception. Another ability provided by Java is data encryption. Our encryption (detailed later) based on DH secret key generator which is used to encrypt and decrypt the data on both sides. To create such a secret key we implemented EKE protocol, based on a common password which is known to both sides. If encryption is enabled on the sender’s side, encryption process is started and an “encryption header” message is sent to the remote device. When the remote device receives this message, an encryption setup process is also started on the receiving end (detailed later). After the encryption has ended successfully and both sides have the same secret key, the card is encrypted under it and transmitted. In the following class diagram, we can see that most of the logic is implemented in the abstract class AbstractBluetoothThread. Both the BluetoothSendThread and BluetoothClientThread inherit from it and reuses the common send/receive logic. The third thread is the BluetoothListenerThread which creates the BluetoothClientThread in case of incoming connection. One of the differences in the logic between the threads is the creation of Bluetooth sockets. The sending thread initiates the connection and gets a socket when a connection is established, while the receiving thread gets the socket from the listening thread which accepted the connection. Another difference is the way the secret key is generated, since the protocol is different for the client side and server side. Both key generators (AliceDHSecretKeyGenerator as sender, BobDHSecretKeyGenerator as receiver) inherit from AbstractDHSecretKeyGenerator, which implements the common key generation logic. After the secret key is generated, we use the CipherGenerator component which receives a secret key or a password to encrypt or decrypt the data. The password is used for initiating the EKE protocol. In the sending process, the data itself is wrapped with a MessageBlock object, which contains the serializable data and the message type. This message block is used by the sending/receiving threads and by the cipher generator in order to encrypt or decrypt existing message block. Another form of message block is the CacheMessageBlock, which contains a temporary cached message. This is used in order to pass business cards from the application to the sending thread, since we can’t pass it through the broadcast Intent because of the card’s size and the intent’s size limit. class crypto Serializable CacheMessageBlock + + + «enumeration» AbstractBluetoothThread:: Status CacheMessageBlock(MessageBlock) getCachedMessage() : MessageBlock remove() : void «enum» Accepted Refused Failed Unknown Serializable MessageBlock + + + + + + + Thread IWatchDogListener AbstractBluetoothThread MessageBlock(String, Serializable) getType() : String getData() : Serializable cache() : CacheMessageBlock isCached() : boolean uncache() : MessageBlock destroy() : void Thread BluetoothListenerThread + + + + + + + AbstractBluetoothThread(String) onTimeout() : void intToByteArray(int) : byte[] byteArrayToInt(byte[]) : int setProgress(int) : void getProgress() : int run() : void + + + BluetoothListenerThread() run() : void cancel() : void BluetoothSendThread BluetoothClientThread «use» + + + BluetoothSendThread(String, MessageBlock) connected() : void ensurePaired(BluetoothDevice, String) : void + BluetoothClientThread(BluetoothSocket) #m_cipher BobDHSecretKeyGenerator AliceDHSecretKeyGenerator + + AliceDHSecretKeyGenerator() getSecretKey(byte[]) : SecretKey + + BobDHSecretKeyGenerator(byte[]) getSecretKey() : SecretKey CipherGenerator + + + + + + CipherGenerator(String) CipherGenerator(SecretKey) encrypt(MessageBlock) : MessageBlock isEncrypted(MessageBlock) : boolean decrypt(MessageBlock) : MessageBlock generateRandomChallenge() : String AbstractDHSecretKeyGenerator + + AbstractDHSecretKeyGenerator(KeyPair) getPublicKey() : byte[] Drawing 4.4.2 – Bluetooth & Encryption class diagram 4.4.1. Send - Receive Sequence This paragraph describes the sending – receiving sequence in details, in chronological order. Receiver: The background service creates a listening thread, which waits for incoming connections. Sender: The user selects a card to send and a device to send it to. The background service receives a send request and creates a sending thread, which connects to the remote device. Receiver: The listening thread accepts the connection and creates a receiving thread, which waits for an incoming message (blocking operation). Sender: The sending thread sends the message type. Sender & Receiver: If message type is “Encrypted” then EKE protocol is started. Receiver: Waits for an incoming message. Sender: Sends the message to the remote device and waits for a status message. Receiver: Receives a message. After a message is received, an answer activity is started according to the message type. Finally, a status message is sent according to user’s answer. sd BusinessCard Device Picker Background Service Background Service Send card Listening Thread New Sending Thread New Connect Accept Receiving Thread New Send(message type) opt Encryption Send(card) GetRunnableBlock(messageType) Answer Activity New Show() :Boolean Send(status) Drawing 4.4.3 – Bluetooth & Encryption class diagram 4.4.2. Encryption Sequence Here is the description of EKE sequence, including the secret key generation based on Diffie-Helman protocol and user authentication. As mentioned before, a common password is used for setting up this encryption method. This is the sequence, as implemented, in chronological order: Step 1 – Client A: User inserts the password, which is scrambled with a hash function. This step is necessary because otherwise an attacker could try to guess the password using a dictionary attack. Sending the hashed password on the communication line instead of the original one is essential for preventing Man-In-The-Middle attack. A DH public key (ga mod p) is encrypted using the hashed password, and sent to client B. Step 2 – Client B: Now client B scrambles the password with the same hash function. With the hashed password he decrypts client A’s public key, and with his own private key, he creates a common DH key – k = gab mod p. Note: g and p are known constant numbers. Since g is very large, we can’t use k and one of the public keys for computing the private ones. In order to enable client A to create the same secret key, we send back client B’s DH public key (gb mod p) encrypted under the hashed password. In addition, we send a random challenge (called challengeB), encrypted under the secret key – k. In each encryption setup a new random challenge is generated, therefore using an old one won’t complete the encryption setup process. This step is necessary because it defends against replay attack and also allows us to authenticate the other side. Step 3 – Client A: Now client A can compute the secret key k, with his own private key and client B’s public key. In order to authenticate that client A is actually client A, we decrypt the received challengeB using the secret key, generate a new challenge (called challengeA), merge them together and encrypt the merged challenge under k. The new challenge is sent back to client B. Since only client A knows the secret key, only he can decrypt the received challengeB and create a new encrypted challenge that contains challengeA and challengeB. Step 4 – Client B: Client B decrypts the received challenge, which consists of challengeA and challengeB. Since he knows challengeB, he can produce challengeA alone and send it back encrypted under the secret key. The fact that only client B knows the secret key k and the original challengeB, he can send back challengeA and prove to client A that he is client B. The secret key we generated here is used for data encryption while sending any data (e.g. cards, statuses and more). This defends the session from session hijacking because even if an attacker would take over the session, and impersonate one of the sides, he can’t understand the messages. sd Use Case Model Client A Client B Device Name, Ew(g^a mod p) w=f(password) Ew(g^b mod p), Ek(challengeB) k=g^ab(mod p) Ek(challengeA,challengeB) Ek(challengeA) Drawing 4.4.4 –Encryption sequence diagram w=f(password) k=g^ab(mod p) 4.5. Business Cards Data Structures This paragraph describes the way business card is represented in our system. Our main considerations while creating this structure were user convenience, memory usage, changeable properties and more… The main idea is that each business card contains many different items, and the user can decide which items he wants in the card. Each item can be edited, and the user can decide about the text, font, color and layout. With the fact that each item is a standalone component, we could implement an editor screen which allows us to handle each item alone, with no relation to other items on the card. One other changeable property of the card is its background. The user can choose a background for his card from the gallery of the device. That means you can take a picture and use it as background. Note that because of its size there was a problem in saving the background as picture in the business card structure, therefore we only saved a reference to the background file. Another capability that we created, based on business card structure, is the themes manager. The themes manager allows the user to apply a theme, which includes items with prepared layout and position, on his card. That means that the texts will remain, but the layout of the card is changed. Also, a user can create a theme from his designed or received cards, and later apply it on other cards. The theme structure is very similar to a business card structure. In order to improve user experience, we added a utility that imports all the phone's contacts and for each contact creates a card based on its details. Note that the contact’s card isn't actually saved on the device, and will be saved only if edited and saved as a card in another directory. In the following class diagram you can see that BusinessCard contains many BusinessCardItem objects. Each item has its type (ItemType), and its layout (BusinessCardItemLayout). You can also see that the layout contains font, size and other parameters. The themes manager (ThemesManager) contains a collection of BusinessCardTheme objects, while each theme contains many items, similar to a BusinessCard structure. When applying a theme, the theme's items would be copied to the business card items. This also includes the background. In order to draw a business card or a theme on the screen, we use the BusinessCardPainter component which allows us to take a business card and create a picture from it, including the background and all of its items. This picture is used in the application’s activities to display the card or the theme. The last component is the ContactUtils, which implements the contact import ability, as described before. class themes Serializable ContactsUtils + + BusinessCardBlock initialize(Context) : void getContacts() : Map<String, BusinessCard> + + BusinessCardBlock(BusinessCard) getBusinessCard() : BusinessCard Serializable BusinessCardItemLayout +Default Serializable BusinessCard + + + + + + + + + + + + + + + + + + + + + BusinessCard(boolean) BusinessCard(BusinessCard) getFileName() : String setFileName(String) : void getItems() : List<BusinessCardItem> getBackgroundFilename() : String getBackground() : BitmapDrawable setBackground(String) : void setBackground(String, Bitmap) : void getFirstName() : String setItem(ItemType, String) : void getLastName() : String getFullName() : String getPhoneNumber() : String getEmail() : String addItem(BusinessCardItem) : void getItem(UUID) : BusinessCardItem removeItem(UUID) : void setItem(BusinessCardItem) : void match(String) : boolean removeItems() : void + + + BusinessCardItemLayout() BusinessCardItemLayout(FontItem, FontSize, int, boolean, boolean, boolean) BusinessCardItemLayout(BusinessCardItemLayout) «enumeration» ItemType +m_layout Serializable BusinessCardItem 1..* + + + + + + BusinessCardItem(ItemType, String) BusinessCardItem(ItemType, String, int, int) BusinessCardItem(ItemType, String, int, int, BusinessCardItemLayout, boolean) GetInputType() : int equals(Object) : boolean equals(BusinessCardItem) : boolean apply theme 1..* Serializable BusinessCardTheme + + + + «use» getName() : String create(Map<ItemType, String>) : BusinessCard apply(BusinessCard) : BusinessCard fromBusinessCard(String, BusinessCard) : BusinessCardTheme BusinessCardPainter + + + + + getBusinessCardAsBitmap(BusinessCard) : Bitmap getBusinessCardAsBitmap(BusinessCard, int) : Bitmap paintBusinessCardItems(Canvas, BusinessCard, int) : void getScale(BusinessCard, int) : float getPaint(Paint, BusinessCardItemLayout, int) : void -m_defaultTheme ThemesManager {leaf} -m_instance + + + + + + + + initialize(Context) : void getInstance() : ThemesManager getThemes() : List<String> getTheme(String) : BusinessCardTheme getDefaultTheme() : BusinessCardTheme save(BusinessCardTheme) : void isDefault(String) : boolean remove(String) : void Drawing 4.5.1 – Business card structure class diagram +m_type «enum» FirstName LastName Name Phone Address Email Company Fax Text Institute WorkPhone Description Profession Department Link 4.6. Business Card Editor The business card editor is made up of an activity that uses a surface view as its drawing surface. The system sends a drawing event which is handled in the onDraw method. The surface view gets redrawn several times a second. Each time we draw the background, and the business card items. Additionally, the editor uses three activities. The first one is the item layout activity, which allows editing the text, setting a type for the item, changing its color, font, size and style. The second is the items list activity which gives a global view of all items in the card and allows editing or removing each item in the same screen. It’s the first thing that opens when a new card is created. The card is created using the default theme and the items are filled with its default values. When this activity opens, the user can edit the text values or remove some of the items. Once “save” is clicked, the surface gets repainted with the updated items. The third activity is the themes selector activity, which allows choosing a theme to apply to the card. When opened it shows the card with the first theme applied on it. By swiping to the left the next theme will be applied to the card and shown on the screen. Once a theme is selected, the surface gets repainted with the selected theme causing items to change position and layout, but not changing the textual values of the items. Using the touch screen the user can manage the position and layout of the business card’s items. When the user clicks on an item in the surface, the topmost item is selected and the surface view is updated to show a bounding box and three clickable icons surrounding the item (edit, delete and move). When selecting the edit icon the item layout activity is opened with the item’s properties. When selecting the delete icon, the item is removed from the card and the surface view. In order to position an item on the card surface, the user can drag the item or the move icon. The editor also uses a menu option which allows selecting a background from the device’s gallery, saving a theme based on the card’s layout, and displaying a grid. The grid can be used to align items on the surface. It also supports snapping to grid lines for accurate alignment. In the following class diagram, the main editor activity is located at the center and the three additional activities are above it and are used by it. Below is the surface view that is interconnected to the activity. There is also a save dialog used to save the card when done. The ItemList and the ItemLayout activities are mainly written with an xml layout and have little dependencies in anything other than the business card structures. The themes activity is based mainly on our framework gallery view code, which creates a very simple tree of views. Like all activities it has a main view which is the header. The header view contains a gallery view of themes. The activity also uses a swipe gesture listener we added to the framework in order to detect swipes. Once a left or right swipe event is detected, we send the gallery view request to show the next or previous theme respectively. class editor SimpleOnGestureListener Sw ipeGestureDetectorListener + + + T SwipeGestureDetectorListener(ISwipeListener) onFling(MotionEvent, MotionEvent, float, float) : boolean onDoubleTap(MotionEvent) : boolean LinearLayout HeaderView ItemsView ViewFactory GalleryView + + # HeaderView(Context) initialize() : void setText(String) : void getView() : View ~m_listener «interface» ISwipeListener -m_themeHeader + + onSwipe(int) : boolean onDoubleTap() : boolean Activity BusinessCardThemeSelector # + + + + + + Activity BusinessCardEditorItemToolbox + - onCreate(Bundle) : void updateControls() : void setSpinner(Spinner, Object) : void onCreate(Bundle) : void setTheme() : void deleteTheme() : void onTouchEvent(MotionEvent) : boolean onDoubleTap() : boolean onSwipe(int) : boolean onCreateOptionsMenu(Menu) : boolean onMenuOpened(int, Menu) : boolean onMenuItemSelected(int, MenuItem) : boolean Activity BusinessCardEditorItemsList + # # onCreate(Bundle) : void setItemsView(LinearLayout, List<BusinessCardItem>) : void saveItems() : void addItemsToBusinessCard() : void onSaveInstanceState(Bundle) : void onRestoreInstanceState(Bundle) : void Android:Activity Activity BusinessCardEditor «use» Dialog UberColorPickerDialog + # UberColorPickerDialog(Context, OnColorChangedListener, int) onCreate(Bundle) : void + + + + + + # + + onCreate(Bundle) : void onCreateOptionsMenu(Menu) : boolean onMenuItemSelected(int, android.view.MenuItem) : boolean saveTheme() : void selectTheme() : void getWidth() : int getHeight() : int selectBackground() : void showEditItems() : void saveBusinessCard() : void makeToast(String) : void showItemToolbox(BusinessCardItem) : void onActivityResult(int, int, Intent) : void getScreenWidth() : int getScreenHeight() : int Sav eInputDialog «use» + showDialog() : void «use» OkCancelDialog + Android:View View BusinessCardEditorSurface + # # # + + + + BusinessCardEditorSurface(BusinessCardEditor, BusinessCard) getGridPaint() : Paint getBoundingBoxPaint() : Paint getTextPaint() : Paint snapToAxis(int, int, int) : int findSelected(int, int) : BusinessCardItem onDraw(Canvas) : void setBackgroundDrawable(Drawable) : void toggleGridLines() : void setBusinessCard(BusinessCard) : void toggleSnapGridLines() : void Drawing 4.6.1 – business card editor class diagram showDialog() : void 4.7. Business Cards Tabs Style Browser In our application there are two methods to manage cards, which can be chosen through application preferences at the main screen. The first method is the tabs browser. In the tabs browser each tab represents a real directory in the file system, except for the special tabs (search, contacts and new). Within each tab, the cards inside that directory are shown as a list. Moving from one tab to another is done by clicking it. One special tab is the search tab, which allows the user to search for cards that contains his search string. If there is a card (in the whole database) that contains this string in one of its items, the card would be shown in the search tab list. Another special tab is the "new…" tab which allows the user to create new tabs. The last special tab is the contacts tab (if enabled), which shows card for each contact in the device (see section 4.5 for extra details). In any tab, if there are cards shown, the user can select them by clicking the wanted card. When selected, a yellow border appears around the card. When a card is selected, the user can use the card through the menu options, to call the phone number in the card, send SMS, send email if an email address exists, and send the card via Bluetooth. The user can also perform file operations, such as moving the card to another directory or deleting it. If the user chooses the edit option, the editor is opened with the selected card, and the user can edit the card items and layout. If no card is selected, it means that the current tab is the selected directory. If the user presses the menu button, directory options appears. The user can delete or rename the selected directory, or create a new directory, which will appear as a new tab. In the following class diagram we can see that the tabs activity contains a collection of ViewBusinessCardTabBase objects. Notice that ViewBusinessCardTabBase is also an activity. This structure is enforced in Android’s tabs implementation. The ViewBusinessCardTabBase includes all the main logic for tabs implementation, and two components inherit from it – the ViewBusinessCardListViewTab and the ViewBusinessCardSearchTab. The last one implements the search tab, as mentioned before. The ViewBusinessCardListViewTab implements a general tab, which represents a directory or the contacts tab. In order to create the card list, we expanded Android’s ListView component and created our own BusinessCardListView. This view uses an expanded adapter, based on Android’s BaseAdapter. This is done in order to create a list with a customized view – a business card in our case. As you can see, the tabs browser uses two additional activities – the device picker and the editor. The device picker is used for sending a card via Bluetooth. When a user wants to send a card, he presses the send option in the menu, and then the device picker is opened. If the user presses on the edit option, the editor opens with the selected card. class v iew er Android:Activ ity Android:ListView TabActivity BaseAdapter Filterable TabsActiv ity BusinessCardsAdapter + + + # + + + + + + + + # # BusinessCardsAdapter(BusinessCardListView) getFilter() : Filter getView(int, View, ViewGroup) : View getImage(BusinessCard) : Bitmap getCount() : int getItem(int) : BusinessCard getItemId(int) : long notifyDataSetChanged() : void onCreate(Bundle) : void setCurrentTab(String) : void getCurrentTab() : String reload() : void addTab(Class<?>, String, String, String, Drawable) : void onDestroy() : void onResume() : void Activity v iew er::BluetoothDev icePicker #m_listView Activity ViewBusinessCardsTabBase ListView OnItemClickListener BusinessCardListView + + + # + BusinessCardListView(Context) onItemClick(AdapterView<?>, View, int, long) : void -m_listView getSelected() : BusinessCard getItems() : List<BusinessCard> notifyDataSetChanged() : void + # # # # + + + # - onCreate(Bundle) : void getListView() : ListView find(String, String) : BusinessCard getBusinessCards() : List<BusinessCard> createBusinessCards(String) : List<BusinessCard> onCreateOptionsMenu(android.view.Menu) : boolean onMenuOpened(int, Menu) : boolean onMenuItemSelected(int, MenuItem) : boolean onResume() : void refresh() : void «use» «use» BusinessCardEditor View BusinessCardsSearchTab View BusinessCardsListView Tab + onCreate(Bundle) : void # + # onStart() : void onCreate(Bundle) : void createBusinessCards(String) : List<BusinessCard> Drawing 4.7.1 – business card editor class diagram # # # # onCreate(Bundle) : void send(int) : void onStart() : void setupBluetooth() : void createDeviceInfo(BluetoothDevice, boolean) discoverDevices() : void stopDiscovery() : void setStatus(String, String) : void onDestroy() : void onActivityResult(int, int, Intent) : void 4.8. Business Cards Gallery Style Browser The second business cards management style is the gallery browser. Like the tabs browser, it organizes the cards into groups managed by the user and displays them in a gallery or in an explorer as icons. The view hierarchy in this activity is made up of several framework code components we created. The first is the gallery view which is a generic view structure that lets the user view images, one at a time, letting the activity that uses it control when to switch to the next view (usually using swipe). It also allows adding arrows to left and right so that the user can touch the arrows instead of swiping. This is the same view we used in the editor for the theme selector activity. The second is the explorer view which is also a generic structure. This one shows the images as small icons allowing scrolling either way and selecting one of the images. Both the gallery view and the explorer view are based on an items container interface and each image is an item in the list managed by the view. This is used both for cards and folders. The third view used here is the multi view. This view is specifically designed to combine the gallery and explorer views together so we can alternate between the visual ways we show the items while using the same list. The gallery browser uses a view hierarchy made up of a header view that contains a search view. The search view also contains a flipper view from android that can switch between two different views. The flipper contains two multi views, one for the folders and the other for the cards themselves. Similar to the tabs activity, cards and folders can be managed through menu options (the same logic is used for both tabs and gallery activities). In the following class diagram we can see the gallery view in the center. It has a reference to the search view in order to control the filter and to the header view in order to control the header text. It also contains a reference to the flipper. When a user clicks on a folder the flipper can update the cards multi view list and flip between these view hierarchies to show the cards inside the folder. The browser activity also uses the editor in order to allow the user to edit a card, and the device picker activity in order to send the selected card to a remote device. class gallery v iew s::Android:View LinearLayout views::SearchView + + + + + + + v iew er::BusinessCardEditor SearchView(Activity) inSearchMode() : boolean showSearch(boolean) : void hideSearch(boolean, IAnimationEnd) : void hideSearch(boolean) : void setFilter(String) : void getFilter() : String + -m_header + -m_search T LinearLayout views::HeaderView FrameLayout MultiView HeaderView(Context) setText(String) : void + + + + + + + + + + + + + + + «use» Activity IMenuActionListener GalleryActiv ity v iew er::Android:Activ ity + + + + + + + onBackPressed() : void onTouchEvent(MotionEvent) : boolean onActionCompleted(MenuAction, Object) : void onActionCanceled(MenuAction) : void onCreateOptionsMenu(Menu) : boolean onMenuOpened(int, Menu) : boolean onMenuItemSelected(int, MenuItem) : boolean MultiView(Context, List<T>) setItems(List<T>) : void getItems() : List<T> setSelected(T) : void getSelected() : T notifyDataChanged() : void empty() : boolean setupSwipe() : void onTouchEvent(MotionEvent) : boolean onSwipe(int) : boolean onDoubleTap() : boolean inExplorer() : boolean showExplorer(boolean) : void hideExplorer(boolean) : void setFilter(String) : void Activity v iew er::BluetoothDev icePicker «use» T T ViewFactory FrameLayout views::ItemsView views::GalleryView + + + + + + + + + GalleryView(Context, List<T>, boolean) showPrevious() : void showNext() : void makeView() : View hasArrows() : boolean isCyclic() : boolean setCyclic(boolean) : void notifyDataChanged() : void setItems(List<T>) : void + + + + + + + + «interface» views::ItemsContainer ItemsView(Context, List<T>) notifyDataChanged() : void setItems(List<T>) : void getItems() : List<T> setSelected(T) : void getSelected() : T setSelectedIndex(int) : void getSelectedIndex() : int + + + + + getSelected() : T setSelected(T) : void getItems() : List<T> setItems(List<T>) : void notifyDataChanged() : void T views::ExplorerView ScrollView v iew s::VerticalScrollView + + + + ExplorerView(Context, List<T>, boolean) notifyDataChanged() : void getLayoutColumnsAmount() : int setLayoutColumnsAmount(int) : void Drawing 4.8.1 – gallery browser class diagram -vscroll + + + VerticalScrollView(Context) onTouchEvent(MotionEvent) : boolean onInterceptTouchEvent(MotionEvent) : boolean 5. Optimizations After implementing the application we tried to optimize its performance. Since Android limits memory usage to 16MB per application, we had to use less memory and more IO. In order to find where we allocated large blocks of memory, we used Eclipse Memory Analyzer and garbage collector logs. From these tools, we found two main activities with the highest memory usage. Most of the memory was for bitmaps storage, which was done for performance enhancement. In order to avoid application crashing due to out of memory exceptions, we cached most of the bitmaps to files and stored only 3 bitmaps in memory at any given time. Another problem was the size of the business card and the fact that we had to “transfer” it between different activities in the application. In Android, in order to send data to another activity, Intent objects are used. The size of an intent is limited and couldn’t contain the entire business card. In order to solve this problem, we cached the card to temporary storage and sent references to the file instead. On the opened activity, we used the reference to get the card’s instance. Based on the results from the memory analyzer of from the logs, it seems that memory problem were solved and the application became more stable. 6. References • Google’s Android Developers – • Wikipedia – • Bluetooth, encryption Security in software applications - Course site – • http://developer.android.com/index.html http://webcourse.cs.technion.ac.il/236350/Spring2010/en/ho_Lectures.html Java docs – http://java.sun.com/j2se/1.5/docs/api/