Changes

Jump to: navigation, search

Teams Winter 2011/team1/BlackBerry/Add Send Email Option

33,187 bytes added, 13:17, 11 April 2011
no edit summary
== 9. Adding Send Email Functionality ==
9.1 Lets first add . Add the api which we will need for Send email option to the email functionalitymenu and implement it: <source lang="java"> import net // Send email to student ImageMenuItem emailItem = new ImageMenuItem("Email Student", 400, 4, MENU_EMAIL); emailItem.rim.blackberry.apisetCommand(new Command(new CommandHandler() { public void execute(ReadOnlyCommandMetadata metadata, Object context) { Student student = (Student) _keywordFilterField.mailgetSelectedElement();</source>
9 if (student != null) { try { ComposeScreen composeScreen = new ComposeScreen(null, _store, student.getEmail()); pushScreen(composeScreen); } catch(Exception ex) { Dialog.2 In order to add send email functionality to our application, we must have the appropriate menu option in our applicationalert("composing screen: " + ex.getMessage()); }
} } })); _mainScreen.addMenuItem(emailItem); </source lang=">9.2 Add four new Screen classes and a helper class to the project:* <code>ComposeScreen.java</code> - start screen where email is composed* <code>MessageScreen.java</code> - screen showing the email* <code>MessagesViewScreen.java</code> - to view the created email* <code>MessageListField.java</code> - handles the drawing of the list of messages* <code>FoldersViewScreen.java"</code>- view emails in the Outbox folderThe main functionality is taken from the Sample provided with blackberry plug-in: <code>BlackBerryMailDemo</code><br/ Email selected student>9.3. Following is the modified code to accommodate the application:<br/>MenuItem emailStudent <code>ComposeScreen.java</code> <source lang= new MenuItem(new StringProvider("Email Studentjava"), 500, 5);>editItem package cs.ecl.setCommand(new Command(new CommandHandler(){team1.project;
public void execute(ReadOnlyCommandMetadata metadata, Object context) { import java.util.*;// TODO Auto-generated method stub import net.rim.blackberry.api.mail.*; import net.rim.device.api.command.*; import net.rim.device.api.ui.component.*; import net.rim.device.api.ui.*; import net.rim.device.api.util.*;
}
}
));
< /source>** * The ComposeScreen is a screen which displays either a new or saved message. * It adds the functionality of saving and sending messages to its parent class, * MessageScreen. */public final class ComposeScreen extends MessageScreen{ private static final int FIRST = 0; private static final int SEND_MENU_ITEM_INDEX = 0; private Store _store; private MessagesViewScreen _messagesViewScreen;
9.3 Now lets get /** * Creates a new ComposeScreen object * @param message A message in the students email address and nameprocess of being composed, or null if a new message is to be composed * @param store The message store for this application */ <source lang="java"> Student student = public ComposeScreen(StudentMessage message, Store store, String email) _keywordFilterField.getSelectedElement { super(message, true, email); String studentEmail _store = store; _messagesViewScreen = student.getEmailnew MessagesViewScreen(); String studentName // If a new message is to be created, indicate this in the title if( message == student.getnamenull ) { setTitle("New Message");</source> }
9.4 Now we must set up a new message // Create and content. Here we create a new message in add menu items specific to the SENT folder of the device and fill it with a predefined bodyCompose action (addTo,<source lang="java"> Store store = Session // addBcc, addCc, etc..getDefaultInstance().getStore(); Folder sentFolder = store.list(Folder.SENT); Message msg AddHeaderFieldAction addToMenuItem = new AddHeaderFieldAction(Message(sentFolder.RecipientType.TO, "Add To: ", "To: "); // Set up recipients Address recipients AddHeaderFieldAction addCcMenuItem = new Address(studentEmail, studentName); //Add the recipient to the message msg.addRecipientsAddHeaderFieldAction(Message.RecipientType.TOCC, "Add Cc: ", recipients); //set a subject for the message msg.setSubject(“Team 1 test email”); //sets the body of the message msg.setContent(“This is a test email sent to"Cc: ” + studentName"); //sets priority msg.setPriority AddHeaderFieldAction addBccMenuItem = new AddHeaderFieldAction(Message.PriorityRecipientType.HIGH); //send the message Transport.send(msgBCC, "Add Bcc: ", "Bcc: ");</source>
9 // MenuItem to save a message MenuItem saveMenuItem = new MenuItem(new StringProvider("Save Message"), 0x230020, 1); saveMenuItem.setCommand(new Command(new CommandHandler() { /** * @see net.rim.device.api.command.CommandHandler#execute(ReadOnlyCommandMetadata, Object) */ public void execute(ReadOnlyCommandMetadata metadata, Object context) { // If the save is completed, then discard this screen if( onSave() ) { close(); } else // If the message could not be saved, alert the user { UiApplication.getUiApplication().invokeLater(new Runnable() { public void run() { Dialog.alert("Message could not be saved"); } }); } } })); // MenuItem to send a message MenuItem sendMenuItem = new MenuItem(new StringProvider("Send Message"), 0x230010, 0); sendMenuItem.setCommand(new Command(new CommandHandler() { /** * @see net.rim.device.api.command.CommandHandler#execute(ReadOnlyCommandMetadata, Object) */ public void execute(ReadOnlyCommandMetadata metadata, Object context) { // If the save is completed, then discard this screen try { _message = getMessage(); if( _message != null ) { // Send the message Transport.send(_message); UiApplication.getUiApplication().pushScreen(_messagesViewScreen); close(); } } catch( MessagingException e ) { ViewStudentApp.errorDialog("Transport.send(Message) threw " + e.toString()); } } }));  addMenuItem(sendMenuItem); addMenuItem(saveMenuItem); addMenuItem(addToMenuItem); addMenuItem(addCcMenuItem); addMenuItem(addBccMenuItem); }  /** * Overrides MessageScreen.displayMessage(). The message's 'sent' properties * are not displayed since the message is still in the process of editing. */ void displayMessage(String email) { // If the message does not exist then compose a new message if( _message == null ) { // Add a To line EditField toField = new EditField("To: ", email, 40, BasicEditField.FILTER_EMAIL); addTextFieldToTableAndScreen(toField, Message.RecipientType.TO);  // Add a subject line EditField subjectField = new EditField("Subject: ", ""); addTextFieldToTableAndScreen(subjectField, SUBJECT);  // Add a separator between the body and the headers add(new SeparatorField());  // Add a body field EditField bodyField = new EditField(); addTextFieldToTableAndScreen(bodyField, BODY); } else // The message exists so display it { displayHeader(); add(new SeparatorField()); displayMessageBody(); } }   /** * Gets a message for sending or saving * @return A new message */ Message getMessage() { // Find an outbox folder and use it to construct a new message Folder outbox = _store.findFolder("Outbox")[ FIRST ]; Message message = new Message(outbox);  // Add all the current headers for( int keyNo = 0; keyNo < HEADER_KEYS.length; keyNo++ ) { Vector fieldsByType = (Vector) _fieldTable.get(HEADER_KEYS[ keyNo ]);  if( fieldsByType != null ) { // Build a vector of all the addresses Vector addressVector = new Vector(); int size = fieldsByType.size(); for( int fieldNo = 0; fieldNo < size; fieldNo++ ) { TextField addressField = (TextField) fieldsByType.elementAt(fieldNo);  // Try to create a new address object wrapping the email // address and add it to the address vector. try { addressVector.addElement(new Address(addressField.getText(), "")); } catch( AddressException e ) // Invalid address { ViewStudentApp.errorDialog("Address(String, String) threw " + e.toString()); } }  // Dump the vector of addresses into an array to send the message Address[] addresses = new Address[ addressVector.size() ]; addressVector.copyInto(addresses);  // Try to add the addresses to the message's list of recipients try { message.addRecipients(HEADER_KEYS[ keyNo ], addresses); } catch( MessagingException e ) { ViewStudentApp.errorDialog("Message#addRecipients(int, Address[]) threw " + e.toString()); } } }  // Add the subject Vector subjectFields = (Vector) _fieldTable.get(SUBJECT); TextField subjectField = (TextField) subjectFields.elementAt(FIRST);  if( subjectFields != null && subjectFields.size() > 0 ) { message.setSubject(subjectField.getText()); }  // Add the body by adding all the body fields into one multipart Vector bodyFields = (Vector) _fieldTable.get(BODY); if( bodyFields != null ) { int size = bodyFields.size(); Multipart content = new Multipart(); for( int fieldNo = 0; fieldNo < size; fieldNo++ ) { TextField body = (TextField) bodyFields.elementAt(fieldNo); content.addBodyPart(new TextBodyPart(content, body.getText())); } try { message.5 Lets setContent(content); } catch any exceptions ( MessagingException e ) { ViewStudentApp.errorDialog("Message#setContent(Object) threw " + e.toString()); } } else { ViewStudentApp.errorDialog("Error: no body field available"); return null; }  // Set the date message.setSentDate(Calendar.getInstance().getTime());  return message; }  /** * @see net.rim.device.api.ui.Screen#onSave() */ protected boolean onSave() { // Save the message to the outbox try { Message newMessage = getMessage(); if( newMessage != null ) { // Retrieve an outbox to save the message in Store store = Session.waitForDefaultSession().getStore(); Folder[] allOutboxFolders = store.list(Folder.OUTBOX);  Folder outbox = null; for( int i = allOutboxFolders.length - 1; i >= 0 ; --i ) { if( allOutboxFolders[ i ].getParent().getName().startsWith("Mailbox") ) { outbox = allOutboxFolders[ i ]; break; } }  // Save the new message and notify replace the user old one if it exists outbox.appendMessage(newMessage); if ( _message != null ) { outbox.deleteMessage(_message, true); } _message = newMessage;  // Set the status to composing and flag that it has been saved _message.setStatus(Message.Status.TX_COMPOSING, Message.Status.TX_ERROR); _message.setFlag(Message.Flag.SAVED, true);  return true; }  return false; } catch( MessagingException e ) { return false; } }  /** * Make "Send" the default menu item. * * @see net.rim.device.api.ui.container.MainScreen#makeMenu(Menu,int) */ protected void makeMenu(Menu menu, int instance) { super.makeMenu(menu, instance);  // menu.setDefault(SEND_MENU_ITEM_INDEX); }  /** * This class is responsible for adding the various header fields to the * compose screen (To, Bcc, CC). */ private final class AddHeaderFieldAction extends MenuItem { private String _fieldLabelText; private int _headerType;  /** * Constructs a menu item which adds a header of a specified type to the * compose screen. * * @param headerType One of the Message.RecipientType fields * @param menuItemText String to use for the menu item * @param fieldLabelText String to use for the label of this field */ AddHeaderFieldAction(int headerType, String menuItemText, String fieldLabelText) { super(new StringProvider(menuItemText), 0x240010, 2);  _fieldLabelText = fieldLabelText; _headerType = headerType; this.setCommand(new Command(new CommandHandler() { /** * Adds a new header field to the message . The field is placed so that * the header types are grouped together and the most recently added one * is closest to the bottom. * @see net.rim.device.api.command.CommandHandler#execute(ReadOnlyCommandMetadata, Object) */ public void execute(ReadOnlyCommandMetadata metadata, Object context) { EditField newField = new EditField(_fieldLabelText, "");  // Find out where the last field of this type was added to the // screen. Vector fieldsByType = (Vector) _fieldTable.get(_headerType); int lastInsertedIndex; if( fieldsByType == null ) { // If a field of _headerType was sentnot made yet, then create the // vector which contains all of the fields of _headerType. fieldsByType = new Vector(); _fieldTable.put(_headerType, fieldsByType); lastInsertedIndex = getIndexForNewFieldType(); } else { lastInsertedIndex = getIndexOfLastFieldOfType(_headerType); }  // Add the new field to both the screen and the vector keeping track // of all the fields of the same type. ComposeScreen.this.insert(newField, lastInsertedIndex + 1); fieldsByType.addElement(newField); newField.setFocus(); } })); }  /** * Given the existing field type of this instance of the class, * determine where to place new header fields in the screen. * * @return The index at which to insert the new header field */ private int getIndexForNewFieldType() { // Note: we don't handle TO here since there ALWAYS must be one TO // field. switch( _headerType ) { // Find the last TO field and use the next index as the // insertion point. case Message.RecipientType.CC: return getIndexOfLastFieldOfType(Message.RecipientType.TO);  // Try to find the last CC field and use it as the next // insertion point. If no CC field exists then find the last // TO field and use its index as the insertion point. case Message.RecipientType.BCC: int index = getIndexOfLastFieldOfType(Message.RecipientType.CC); if( index == -1 ) return getIndexOfLastFieldOfType(Message.RecipientType.TO); return index;  default: throw new IllegalStateException("Mail Demo: Unrecognized recipient type"); } }  /** * Retrieves the index of the last field added of a specified type. * * @param type The type of header field to retrieve the last index of * @return The index of the most recently added field of the specified * type, -1 if a field of the specified type has not been added * yet. */ private int getIndexOfLastFieldOfType(int type) { Vector fields = (Vector) _fieldTable.get(type); if( fields == null ) { return -1; }  Field field = (Field) fields.lastElement();  return field.getIndex(); } } }  </source><code>MessageScreen.java</code> <source lang="java"> package cs.ecl.team1.project;  import net.rim.device.api.ui.container.*; import net.rim.device.api.ui.component.*; import net.rim.device.api.util.IntHashtable; import javax.microedition.pim.Contact; import java.util.*;  import net.rim.blackberry.api.mail.*;  /** * The MessageScreen class allows a user to view a selected message and * edit the message if the screen is marked editable. It manages the different * TextFields using a hashtable where the type of information that is held * in a given TextField is the key while the value is a Vector of TextFields * associated with that information type. This class supports displaying * plain text, Mime, supported and unsupported attachments and pdap contacts. */ public class MessageScreen extends MainScreen { // Constants public final static String NO_SUBJECT = "<No Subject>"; public final static String UNKNOWN_NAME = "<?>";  protected final static int SUBJECT = 0; protected final static int BODY = 1; protected final static int INFO = 2; protected final static int[] HEADER_KEYS = { Message.RecipientType.TO, Message.RecipientType.CC, Message.RecipientType.BCC }; protected final static String[] HEADER_NAMES = { "To: ", "Cc: ", "Bcc: " };  private final static int MAX_CHARS = 128;  protected IntHashtable _fieldTable; protected Message _message; private boolean _editable;  /** * Creates a new MessageScreen object * @param message The message to display * @param editable True is the message is editable, otherwise false */ public MessageScreen(Message message, boolean editable, String email) { _fieldTable = new IntHashtable(); _editable = editable;  // Set the message and display its subject as the title if the // message exists. _message = message; if( _message != null ) setTitle(_message.getSubject());  displayMessage(email); }  /** * Displays the message */ void displayMessage(String email) { displayMessageInformation();  add(new SeparatorField());  displayHeader();  add(new SeparatorField());  displayMessageBody(); }  /** * Displays information about the message's send and recieve properties */ protected void displayMessageInformation() { // Add a field describing the source service ServiceConfiguration sc = _message.getFolder().getStore().getServiceConfiguration(); EditField service = new EditField("Service: ", sc.getName(), MAX_CHARS, EditField.READONLY | EditField.NON_FOCUSABLE); addTextFieldToTableAndScreen(service, INFO);  // Add the folder field EditField folder = new EditField("Folder: ", _message.getFolder().getName(), MAX_CHARS, EditField.READONLY | EditField.NON_FOCUSABLE); addTextFieldToTableAndScreen(folder, INFO);  // Add the status of the message String statusString = getStatusString(_message); EditField status = new EditField("Status: ", statusString, MAX_CHARS, EditField.READONLY | EditField.NON_FOCUSABLE); addTextFieldToTableAndScreen(status, INFO); }  /** * Displays information about the destination and source of the message as * well as its subject. */ protected void displayHeader() { // Assign the appropriate EditField style property long editableStyle = _editable ? EditField.EDITABLE : EditField.READONLY;  // Display the headers (To:, Cc:, Bcc:) for( int key = 0; key < HEADER_KEYS.length; key++ ) { try { Address[] addresses = _message.getRecipients(HEADER_KEYS[ key ]); for( int index = 0; index < addresses.length; index++ ) { // Retrieve the name String name = addresses[ index ].getName(); if( name == null || name.length() == 0 ) { name = addresses[ index ].getAddr(); }  // Create the edit field, associate the address to the field // and add it to the screen and collection of fields. EditField headerField = new EditField(HEADER_NAMES[ key ], name, EditField.DEFAULT_MAXCHARS, editableStyle); headerField.setCookie(addresses[ index ]);  addTextFieldToTableAndScreen(headerField, HEADER_KEYS[ key ]); } } catch (Exception meMessagingException e ) { ViewStudentApp.errorDialog("Error: could not retrieve message header."); close(); } }  // Display the 'Sent' date if it is available Date sent = _message.getSentDate(); if( sent != null ) { EditField sentDate = new EditField("Sent: ", Util.getDateAsString(sent), EditField.DEFAULT_MAXCHARS, EditField.READONLY | EditField.NON_FOCUSABLE);  // Change the label to "Saved: " if the message hasn't been sent yet if( _message.getStatus() == Message.Status.TX_COMPOSING ) sentDate.setLabel("Saved: ");  add(sentDate); }  // Display the subject field String subject = _message.getSubject(); if( subject == null ) subject = NO_SUBJECT;  EditField subjectField = new EditField("Subject: ", subject, EditField.DEFAULT_MAXCHARS, editableStyle); addTextFieldToTableAndScreen(subjectField, SUBJECT); }  /** * Displays the message body */ protected void displayMessageBody() { // Retrieve the parent of the message body Object obj = _message.getContent(); Multipart parent = null; if( obj instanceof MimeBodyPart || obj instanceof TextBodyPart ) { BodyPart bp = (BodyPart) obj; parent = bp.getParent(); } else { parent = (Multipart) obj; }  // Display the message body String mpType = parent.getContentType(); if( mpType.equals(BodyPart.ContentType.TYPE_MULTIPART_ALTERNATIVE_STRING) || mpType.equals(BodyPart.ContentType.TYPE_MULTIPART_MIXED_STRING) ) { displayMultipart(parent); }  // Ensure there is at least one body field if nothing was displayed Vector bodyVector = (Vector) _fieldTable.get(BODY); if( bodyVector == null || bodyVector.size() == 0 ) { if( _editable ) { addTextFieldToTableAndScreen(new EditField("", ""), BODY) ; } else { addTextFieldToTableAndScreen(new RichTextField(""), BODY); } } }  /** * Processes a multi-part message by displaying its body parts. Text body * parts are displayed before attachments and if a multi body part is * encountered, then it is processed through recursion by calling this method * on it. * * @param multipart The multi-part to display * @param editable True if this multi-part is editable */ Systemprotected void displayMultipart(Multipart multipart) { // This vector stores fields which are to be displayed only after all // of the body fields are displayed. (Attachments and Contacts). Vector delayedFields = new Vector();  // Process each part of the multi-part, taking the appropriate action // depending on the part's type. This loop should: display text and // html body parts, recursively display multi-parts and store // attachments and contacts to display later. for( int index = 0; index < multipart.getCount(); index++ ) { BodyPart bodyPart = multipart.getBodyPart(index);  // If this body part is text then display all of it if( bodyPart instanceof TextBodyPart ) { TextBodyPart textBodyPart = (TextBodyPart) bodyPart;  // If there are missing parts of the text, try to retrieve the // rest of it. if( textBodyPart.errhasMore() ) { try { Transport.printlnmore(metextBodyPart, true); } catch( Exception e ) { Dialog ViewStudentApp.errorDialog("Transport.alertmore(studentName BodyPart, boolean) threw " + e.toString()); } } String plainText = (String) textBodyPart.getContent();  // Display the plain text, using an EditField if the message is // editable or a RichTextField if it is not editable. Note: this // does not add any empty fields. if( plainText.length() != 0 ) { if( _editable ) { addTextFieldToTableAndScreen(new EditField(" ", plainText), BODY); } else { addTextFieldToTableAndScreen(new RichTextField(plainText), BODY); } } } else if( bodyPart instanceof MimeBodyPart ) { MimeBodyPart mimeBodyPart = (MimeBodyPart) bodyPart;  // If the content is text then display it String contentType = mimeBodyPart.getContentType(); if( contentType.startsWith(BodyPart.ContentType.TYPE_TEXT_HTML_STRING) ) { Object obj = mimeBodyPart.getContent(); if( obj != null ) { String htmlText = new String((byte[]) obj); addTextFieldToTableAndScreen(new RichTextField(htmlText), BODY); } } else if( contentType.equals(BodyPart.ContentType.TYPE_MULTIPART_ALTERNATIVE_STRING) ) { // If the body part is a multi-part and it has the the // content type of TYPE_MULTIPART_ALTERNATIVE_STRING, then // recursively display the multi-part. Object obj = mimeBodyPart.getContent(); if( obj instanceof Multipart ) { Multipart childMultipart = (Multipart) obj; String childMultipartType = childMultipart.getContentType(); if( childMultipartType.equals(BodyPart.ContentType.TYPE_MULTIPART_ALTERNATIVE_STRING) ) { displayMultipart(childMultipart); } } } } else if( bodyPart instanceof SupportedAttachmentPart || bodyPart instanceof UnsupportedAttachmentPart ) { // Extract the content type and name from the attachments String contentType = bodyPart.getContentType(); String name; if( bodyPart instanceof UnsupportedAttachmentPart ) { UnsupportedAttachmentPart uap = (UnsupportedAttachmentPart) bodyPart; name = uap.getName(); } else // The bodyPart is a SupportedAttachmentPart { SupportedAttachmentPart sap = (SupportedAttachmentPart) bodyPart; name = sap.getName(); }  // Format the content type and name to display and store // the field. StringBuffer sb = new StringBuffer(contentType.length() + name.length() + 2); sb.append(contentType); sb.append('['); sb.append(name); sb.append(']');  delayedFields.addElement(new RichTextField(sb.toString())); } else if( bodyPart instanceof PDAPContactAttachmentPart ) { Contact contact = (Contact) bodyPart.getContent();  // Build the contact name StringBuffer sb = new StringBuffer("Contact: "); if( contact.countValues(Contact.NAME) > 0 ) { String[] name = contact.getStringArray(Contact.NAME, 0);  if( name[ Contact.NAME_PREFIX ] != null ) { sb.append(name[ Contact.NAME_PREFIX ]); sb.append(' '); }  if( name[ Contact.NAME_GIVEN ] != null ) { sb.append(name[ Contact.NAME_GIVEN ]); sb.append(' '); }  if( name[ Contact.NAME_FAMILY ] != null ) { sb.append(name[ Contact.NAME_FAMILY ]); }  // Trim the last space of the name if it exists int lastChar = sb.length() - 1; if( sb.charAt(lastChar) == ' ' ) sb.deleteCharAt(lastChar); } else { sb.append(UNKNOWN_NAME); }  // Create the contact attachment field and store it RichTextField contactAttachment = new RichTextField(sb.toString()); contactAttachment.setCookie(contact); delayedFields.addElement(contactAttachment); } }  // Now that the body parts have been emaileddisplayed, display the queued // fields while separating them by inserting a separator field. for( int index = 0; index < delayedFields.size(); index++ ) { add(new SeparatorField()); addTextFieldToTableAndScreen((TextField) delayedFields.elementAt(index), BODY); } }  /** * Compiles the status of a message into a readable string. * * @param message The message whose status is to be compiled into a string * @return The string displaying the status of the message */ public static String getStatusString(Message message) { StringBuffer statusStrBuffer = new StringBuffer();  // Add any errors to the status string if it applies int status = message.getStatus(); if( status == Message.Status.RX_ERROR ) { statusStrBuffer.append("RX ERROR, "); }  if( status == Message.Status.TX_GENERAL_FAILURE ) { statusStrBuffer.append("RX ERROR, "); }  if( status == Message.Status.TX_ERROR ) { statusStrBuffer.append("TX ERROR, "); }  // Use the flags to add any message statuses int flags = message.getFlags(); if( 0 != (flags & Message.Flag.OPENED) ) { statusStrBuffer.append("Opened, "); }  if( 0 != (flags & Message.Flag.SAVED) ) { statusStrBuffer.append("Saved, "); }  if( 0 != (flags & Message.Flag.FILED) ) { statusStrBuffer.append("Filed, "); }  // Check if the message has a high or low priority byte messagePriority = message.getPriority(); if( messagePriority == Message.Priority.HIGH ) { statusStrBuffer.append("High Priority, "); } else if( messagePriority == Message.Priority.LOW ) { statusStrBuffer.append("Low Priority, "); }  // If there are any characters in the status string then delete the last // two characters if there are any characters to delete. Should be // either ", " or " ". statusStrBuffer.delete(statusStrBuffer.length() - 2, statusStrBuffer.length());  return statusStrBuffer.toString(); }  /** * Add a new field to the hashtable of TextFields and to the screen * * @param field The field to add * @param type The type of field to add */ protected void addTextFieldToTableAndScreen(TextField field, int type) { Vector fieldsByType = (Vector) _fieldTable.get(type);  // If the vector of fields associated with the type is not made yet, // initialize one and put it into the fields collection. if( fieldsByType == null ) { fieldsByType = new Vector(1); _fieldTable.put(type, fieldsByType); }  fieldsByType.addElement(field); add(field); }  /** * @see net.rim.device.api.ui.Screen#onClose() */ public boolean onClose() { // If the message status is "received", mark it "read" if( _message != null && _message.getStatus() == Message.Status.RX_RECEIVED ) { _message.setStatus(Message.Status.TX_READ, Message.Status.TX_ERROR); _message.setFlag(Message.Flag.OPENED, true); }  return super.onClose(); } } </source>Other classes stay unchanged.<br/>9.4. Run the application, select a user from the list, and select Email Student from the menu:<br/>[[Image: BB_email1.png | 300px]][[Image: BB_email2.png | 300px]]<br/>9.5. Type in the subject and some text in the body, and select Send Email from the menu:<br/>[[Image: BB_email3.png | 300px]]<br/>9.6. The messageList screen is displayed showing the created email. Select Folder View from the menu to see the Outbox folder:<br/>[[Image: BB_email4.png | 300px]][[Image: BB_email5.png | 300px]]
1
edit

Navigation menu