Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Save more on your purchases! discount-offer-chevron-icon
Savings automatically calculated. No voucher code required.
Arrow left icon
All Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Newsletter Hub
Free Learning
Arrow right icon
timer SALE ENDS IN
0 Days
:
00 Hours
:
00 Minutes
:
00 Seconds

How-To Tutorials - Mobile

213 Articles
article-image-cocos2d-iphone-surfing-through-scenes
Packt
29 Dec 2010
10 min read
Save for later

Cocos2d for iPhone: Surfing Through Scenes

Packt
29 Dec 2010
10 min read
  Cocos2d for iPhone 0.99 Beginner's Guide Make mind-blowing 2D games for iPhone with this fast, flexible, and easy-to-use framework! A cool guide to learning cocos2d with iPhone to get you into the iPhone game industry quickly Learn all the aspects of cocos2d while building three different games Add a lot of trendy features such as particles and tilemaps to your games to captivate your players Full of illustrations, diagrams, and tips for building iPhone games, with clear step-by-step instructions and practical examples         Read more about this book       (For more resources on Cocos2d, see here.) We'll be doing a lot of things in this article, so let's get started. Aerial Gun, a vertical shooter game Let's talk about the game we will be making. Aerial Gun, as I said earlier, is a vertical shooter game. That means you will be in control of an airship which will move vertically. Actually, the airship won't be moving anywhere (well except to the left and right); what is really going to move here is the background, giving the sense the airship is the one moving. The player will be able to control the airship by using accelerometer controls. We'll also provide some areas where the player can touch to fire bullets or bombs to destroy the enemies. Enemies will be appearing at different time intervals and will have some different behaviors attached to them. For example, some of them could just move towards the airship, others may stay there and shoot back, and so on. We'll do it in a way you can create more custom behaviors later. For this game we will be using the Cocos2d template again, just because it is the easier way to have a project properly set up, at least to begin our work. So, follow the same steps as when we created the Coloured Stones game. Just open Xcode and go to the File menu, select to create a new project. Then choose the Cocos2d template (the simple one, without any physics engine) and give a name to the project. I will call it AerialGun. Once you do that, your new project should be opened. Creating new scenes We will begin this new game by first doing a couple of scenes other than the one that holds the actual game. If you take a look at the class that the template generates, at first sight you won't find what would appear to be a scene. That is because the template handles that in a confusing fashion, at least for people who are just getting started with Cocos2d. Let's take a look at that. Open the newly generated HelloWorldScene.m file. This is the same code in which we based our first game. This time we will analyze it so you understand what it is doing behind scenes. Take a look at the first method of the implementation of the HelloWorld Layer: +(id) scene{ // 'scene' is an autorelease object. CCScene *scene = [CCScene node]; // 'layer' is an autorelease object. HelloWorld *layer = [HelloWorld node]; // add layer as a child to scene [scene addChild: layer]; // return the scene return scene;} If you remember well, this is the method that get's called in the AppDelegate when the Director needs to start running with a scene. So why are we passing the method of a layer instead of an instance of a CCScene class? If you pay attention to the +(id)scene method of the layer, what it does is to instantiate a CCScene object, then it instantiates a HelloWorld object (the layer), and then it adds that layer to the scene and returns it. This actually works as you have witnessed and is pretty quick to set up, and get you up and running. However, sometimes you will need to have you own custom scenes, that is a class that inherits from CCScene and extends it in some fashion. Now we are going to create some of the scenes that we need for this game and add a layer to each one. Then when it is time to work with the game scene we will modify it to match our needs. Before doing anything, please change the name of the HelloWorldlayer to GameLayer and the name of the HelloWorldScene to GameScene, just as we did back then with our first game. Time for action – creating the splash and main menu scene We will begin with a simple scene, the splash screen. A splash screen is the first thing that appears as you launch a game. Well, the second if you count the Default.png image. The objective of this screen is to show the player some information about the developer, other companies that helped, and so on. Most times you will just show a couple and logos and move to the main menu. So, what we will do now is put a new Default.png image, then create the SplashScene. The Default.png image is located in your project's Resources group folder and it is the first image that is shown when the application is launched. You should always have one, so that something is shown while the application is being launched. This happens before anything is initialized, so you can't do anything else other than show this image. Its dimensions must be 320 * 480 (when developing for older generation iPhones), so if your game is supposed to be in landscape mode, you should rotate the image with any graphics software before including it in your project. The SplashScene is going to show a sprite for a moment, then fade it, show another one and then move to the GameScene. Let's add a new file to the project. Select New File (CMD + N) from the File menu, then select Objective-C class (we are going to do it from scratch anyways) and name it SplashScene. This file will hold both the SplashScene and the SplashLayer classes. The SplashLayer will be added as a child of the SplashScene, and inside the layer we will add the sprites. Before writing any code, add to the project the three splash images I created for you. You can find them in the companion files folder. Once you have them added into your project we can begin working on the SplashScene. The following is the SplashScene.h: #import <Foundation/Foundation.h>#import "cocos2d.h"#import "MainMenuScene.h"@interface SplashScene : CCScene { }@end@interface SplashLayer : CCLayer { }@end And the SplashScene.m file: #import "SplashScene.h" //Here is the implementation of the SplashScene@implementation SplashScene- (id) init{ self = [super init]; if (self != nil) { [self addChild:[SplashLayer node]]; } return self;}-(void)dealloc{ [super dealloc];}@end//And here is the implementation of the SplashLayer@implementation SplashLayer- (id) init{ if ((self = [super init])) { isTouchEnabled = YES; NSMutableArray * splashImages = [[NSMutableArray alloc]init]; for(int i =1;i<=3;i++) { CCSprite * splashImage = [CCSprite spriteWithFile:[NSString stringWithFormat:@"splash%d.png",i]]; [splashImage setPosition:ccp(240,160)]; [self addChild:splashImage]; if(i!=1) [splashImage setOpacity:0]; [splashImages addObject:splashImage]; } [self fadeAndShow:splashImages]; } return self;}//Now we add the methods that handle the image switching-(void)fadeAndShow:(NSMutableArray *)images{ if([images count]<=1) { [images release]; [[CCDirector sharedDirector]replaceScene:[MainMenuScene node]]; } else { CCSprite * actual = (CCSprite *)[images objectAtIndex:0]; [images removeObjectAtIndex:0]; CCSprite * next = (CCSprite *)[images objectAtIndex:0]; [actual runAction:[CCSequence actions:[CCDelayTime actionWithDuration:2], [CCFadeOut actionWithDuration:1],[CCCallFuncN actionWithTarget:self selector:@selector(remove:)],nil]]; [next runAction:[CCSequence actions:[CCDelayTime actionWithDuration:2], [CCFadeIn actionWithDuration:1],[CCDelayTime actionWithDuration:2], [CCCallFuncND actionWithTarget:self selector:@selector(cFadeAndShow: data:) data:images],nil]]; } }-(void) cFadeAndShow:(id)sender data:(void*)data{ NSMutableArray * images = (NSMutableArray *)data; [self fadeAndShow:images];}-(void)remove:(CCSprite *)s{ [s.parent removeChild:s cleanup:YES];}-(void)dealloc{ [super dealloc];}@end As you may notice, I have put together two classes in only one file. You can do this with any number of classes, as long you don't get lost in such a long file. Generally, you will create a pair of files (the .m and .h) for each class, but as the SplashScene class has very little code, I'd rather put it there. For this to work properly, we need to make some other changes. First, open the AerialGunAppDelegate.m file and change the line where the the Director starts running the GameScene. We want it to start by running the SplashScene now. So replace that line with the following: [[CCDirector sharedDirector] runWithScene:[SplashScene node]]; Also remember to import your SplashScene.h file in order for the project to properly compile. Finally, we have to create the MainMenuScene, which is the scene the Director will run after the last image has faded out. So, let's create that one and leave it blank for now. The following is the MainMenuScene.h file: #import <Foundation/Foundation.h>#import "cocos2d.h"@interface MainMenuScene : CCScene { }@end@interface MainMenuLayer : CCLayer { }@end The following is the MainMenuScene.m file: #import "MainMenuScene.h"@implementation MainMenuScene- (id) init{ self = [super init]; if (self != nil) { [self addChild:[MainMenuLayer node]]; } return self;}-(void)dealloc{ [super dealloc];}@end@implementation MainMenuLayer- (id) init{ if ((self = [super init])) { isTouchEnabled = YES; } return self;}-(void)dealloc{ [super dealloc];}@end That would be all for now. Run the project and you should see the first image appear. Then fade to the next one after a while and continue till the last one. Once the last one has faded out, we move on to the MainMenuScene. What just happened? Creating a new scene is as easy as that. You can see from the MainMenuScene code that what we are doing is quite simple; when the MainMenuScene gets created we just instantiate the MainMenuLayer and add it to the scene. That layer is where we will later add all the necessary logic for the main menu. The MainMenuScene as well as the SplashScene both inherit from the CCScene class. This class is just another CCNode. Let's take a little look at the logic behind the SplashScene: NSMutableArray * splashImages = [[NSMutableArray alloc]init];for(int i =1;i<=3;i++){ CCSprite * splashImage = [CCSprite spriteWithFile:[NSString stringWithFormat:@"splash%d.png",i]]; [splashImage setPosition:ccp(240,160)]; [self addChild:splashImage]; if(i!=1) [splashImage setOpacity:0]; [splashImages addObject:splashImage];} [self fadeAndShow:splashImages]; This piece of code is from the SplashLayer init method. What we are doing here is creating an array that will hold any amount of sprites (in this case, three of them). Then we create and add those sprites to it. Finally, the fadeAndShow method is called, passing that newly created array to it. The fadeAndShow method is responsible for fading the images it has. It grabs the first image in the array (after that, the sprite is removed from the array). It then grabs the next one. Then it applies actions to both of them to fade them in and out. The last action of the second sprite's action is a CCCallFuncND, which we use to call the fadeAndShow method again with the modified array. This occurs if there is more than one remaining sprite in the array. If there isn't, the fadeAndShow method calls the Director's replaceScene method with the MainMenuScene. I have made the SplashLayer logic, so you can add more splash images to the array (or leave just one) if you like. Generally, just one or two images will be more than enough.
Read more
  • 0
  • 0
  • 1762

article-image-interfacing-personal-information-management-pim-applications-blackberry
Packt
13 Aug 2010
17 min read
Save for later

Interfacing with Personal Information Management (PIM) Applications in BlackBerry

Packt
13 Aug 2010
17 min read
(For more resources on BlackBerry, see here.) The BlackBerry handhelds come pre-loaded with many great programs to help make a person more productive. While messages may be the most common reason a person will purchase a BlackBerry, the other Personal Information Management (PIM) applications often quickly become essential as well. Not only can you interface with these applications by adding or editing content in them, you can also listen for events that allow you to react to things that happen. Some of the applications even allow you to add menu items and other "active content" to them. That's a lot to talk about, so we'll just focus on some of the most common tasks to get you started in this article. As a developer, you cannot ignore the other applications on the handheld. The more integrated an application can be with these standard applications, the better the user experience will generally be. Our TipCalc application is very specialized, and one of the few that works well without integrating with other applications. More often than not though, any applications that you create will benefit from some level of integration. Introducing PIM The first area that we will take a look at is the Personal Information Management, or PIM applications and data. PIM applications are a rather generic name for a group of tools that manage your personal information, especially as it relates to your handheld. This could be stretched to include a lot of things, but it generally means your messages, contacts, and scheduling information that help you to manage your life. In BlackBerry terms it means the Messages, Address Book, Calendar, Tasks, and Notes. Access to the PIM data in the BlackBerry SDK is provided through the JSR-75 specification, which is a Java standard. Like many of the Java standards in the BlackBerry SDK, there are also BlackBerry-specific extensions available that expand the basic classes with new BlackBerry-specific functionality. Like many of the other standards we find in Java, JSR-75 implements a factory pattern where one class, in this case the PIM class, is used to create objects for the other more specific types of PIM data. The PIM class can basically do only one thing and that is to retrieve a PIMList object that contains a bunch of specialized PIMItem objects. Why is all so generic? All of these PIM classes may seem very generic and you would be absolutely correct. They are generic and they are supposed to be that way. PIM data is a very generic concept so the implementation is very generic as well. Also, because it is a Java standard, it needs to be flexible enough to accommodate any system that it might be implemented on. A perfect example of this kind of flexibility is the BlackBerry PIN field. The BlackBerry PIN is an entry in your address book and therefore, it should be included in the PIM data that you get. However, a PIN is a BlackBerry-specific concept and no other device out there will use it. You can't really expect the Java standard to include specialized fields for every possible piece of data that some device may have or want to include. The answer to this is to present PIM data in a key-value pairing so that it is flexible enough to handle every possible scenario. A key-value pairing is a somewhat technical term to describe the pattern for storing values based on a static key. Or, more simply, if you know the proper key you can access the value. The flexible part is that the PIM object storing all of the values does not need to know about each specific value or provide any special mechanism for accessing each specific value. All access is done through generic methods, which also require the key. The difficulty in using this kind of approach is that the keys must be common knowledge. In addition, simple numeric keys do not support self-documenting code or even easily readable code. Keys that are string values offer a lot of advantages—in that the keys are much more readable, but the possibility for mistakes is very great because you don't have the compiler to help ensure that only correct keys are used. To help solve these issues there are derived classes for each type of PIM item. While you can do nearly everything by using the generic classes that a derived class would offer, I wouldn't recommend it. These classes are here to make your code easier to write and read, and should be used. PIMLists As we said early on, the PIM class is used primarily to retrieve a PIMList object for a specific kind of PIM item, that is, address book contact, calendar event, and so on. For each of these types, there is also a specialized class that you can use instead of the generic PIMList class. Classes such as ContactList, EventList, and ToDoList offer a specialized version of the more generic PIMList class. These specialized classes are also part of the Java standard and should be preferred because they offer a few more methods which are specific to that kind of data. There are BlackBerry-specific versions of these classes as well. Therefore, the BlackBerryContactList class is the BlackBerry-specific version of the ContactList, which is in turn a specialized version of PIMList for contact data. Generally speaking, you will want to use the BlackBerry-specific versions of PIMList classes when making your applications. PIMItems A PIMItem is the generic representation for any piece of PIM data. Just like there are specific versions of the PIMList, there are also specific versions of the PIMItem class for each kind of PIMItem. Contact, Event, and ToDo are all specific versions of a PIMItem for that kind of PIM data. As you might expect, there are BlackBerry-specific versions as well. BlackBerryContact, BlackBerryEvent, and BlackBerryToDo all exist to extend and further specialize the standard Java classes. These specialized classes aren't as specialized or easy to use as one might expect though. Providing a method called getFirstName might be really useful, but unfortunately, you will find nothing of the sort. The specialized classes offer few methods for accessing data. Instead, they provide static values for the keys used to set and retrieve data from the PIMItem class. Remember, earlier we noted that one drawback to using this kind of key-value pairing was that keys were sometimes not clear and that you could not expect help from the compiler. By providing each key value in the specialized class, both of these goals are accomplished. The name of the key value now provides a readable name and the compiler will flag an error if there is a typo or problem with the constant value being used. Another aspect of PIMItem is that each value that an item has a specific type associated with it as well. Some of these are obvious, such as the start date of an event using a Date type. Some of them, such as the Name field of a Contact that requires an array, are not. Some fields can be given a subtype as well, such as the Phone field. With the subtype you can specify what kind of phone number it is: home, work, or mobile. Furthermore, some of the fields can have multiple occurrences while others cannot. A good example of this is the Email field in a Contact. A contact is allowed to have up to three e-mail addresses, but there is no subtype associated with them like there is with phone numbers. The bottom line to all this is that the PIM items have a defined structure to them and they won't allow just any value to be put into a field. The documentation plays a big role here in understanding this because there are no field-specific methods to provide some additional assistance in the proper way to access each field. Laying the ground work Still, this is all rather abstract because you haven't seen any real code samples yet, so let's get into some code! For this article, you will build an application that someone will use to request some time off from their manager. This is definitely one of those applications that just can't be done without interfacing with other applications on the handheld! To make getting started a little easier we will take the starter TimeOff application from the code bundle and add to it throughout this article. The first task to undertake is one to help make testing and debugging easier. Remember, you will be working on the simulator, which is essentially a brand new device and which can be often reset. That means you don't have any of your contacts there! You will need some contacts later, so to get started let's add a menu item to the application that will create a few contacts that you can later use to test with. Time for action - creating test contacts Modify the _AddTestAddressesAction menu item in the TimeOff project to look like the following completed code. protected MenuItem _AddTestAddressesAction = new MenuItem( "Add Test Data", 800000, 50){ public void run() { PIM pimInstance = PIM.getInstance(); try { // TODO: Create test contacts BlackBerryContactList contacts = (BlackBerryContactList)pimInstance.openPIMList( PIM.CONTACT_LIST, PIM.READ_WRITE); BlackBerryContact newContact1 = (BlackBerryContact)contacts.createContact(); BlackBerryContact newContact2 = (BlackBerryContact)contacts.createContact(); String[] names = new String[contacts.stringArraySize(BlackBerryContact.NAME)]; names[BlackBerryContact.NAME_FAMILY] = "Smith"; names[BlackBerryContact.NAME_GIVEN] = "John"; if (contacts.isSupportedArrayElement(Contact.NAME, Contact.NAME_SUFFIX)) { names[BlackBerryContact.NAME_SUFFIX]="Jr"; } newContact1.addStringArray( BlackBerryContact.NAME, BlackBerryContact.ATTR_NONE, names); names[Contact.NAME_FAMILY] = "Doe"; names[Contact.NAME_GIVEN] = "John"; if (contacts.isSupportedArrayElement(Contact.NAME, Contact.NAME_PREFIX)) { names[Contact.NAME_PREFIX] = "Dr."; } newContact2.addStringArray(Contact.NAME, Contact.ATTR_NONE, names); //TODO: Add Phone numbers //TODO: Add Email Addresses //TODO: Add Addresses newContact1.commit(); newContact2.commit(); } catch (PIMException e) { // TODO Auto-generated catch block e.printStackTrace(); } }}; Then add this line to the constructor to make the menu item available when you run the application. this.addMenuItem(_AddTestAddressesAction); What just happened? This is the first of several baby steps as you work towards the goal of creating some test contacts in the address book in the simulator. As the address book in the simulator doesn't have any entries to begin with, and can be erased frequently, doing this provides you with a way to quickly and easily create or recreate the contacts you will use later on for testing other parts of this application. It also happens to be a great way to demonstrate how to add contacts. This first baby step does only a few things. First, it gets a PIMList object for contacts and then creates two new contacts. After this it sets the name of each one and finally commits the records into the address book. These steps make sense at a high level, but let's take a look at the details. The first step is to get an instance to the PIM object, which is done through a static method in the PIM class called getInstance. PIM pimInstance = PIM.getInstance(); Once you have an instance of PIM, the next step is to get a list of contact items using the openPIMList method on the instance you just retrieved. This same method is used to get a list of any kind of PIM item so you must specify the type of data to get as one of the parameters. The PIM class offers constant values for every kind of PIM item, so in this case, use the constant PIM.CONTACT_LIST. As you plan to add new contacts, the next parameter needs to be the constant PIM.READ_WRITE so that you have write permissions. It's always good practice to request the minimum amount of permissions that you need, so if your application doesn't change or add data to the list you should simply use the PIM.READ permission. As we touched on earlier, this method returns a generic PIMList type so you also have to cast it to the appropriate specialized type. If a list type of CONTACT_LIST has been specified, you can cast the resulting PIMList to either of the available specialized classes—ContactList or BlackBerryContactList. As long as your application is a BlackBerry-specific application, there is no good reason to use the less specialized class of ContactList. Instead, you should always use BlackBerryContactList. BlackBerryContactList contacts = (BlackBerryContactList)pimInstance.openPIMList (PIM.CONTACT_LIST, PIM.READ_WRITE); The next step is to create a couple of new contacts that you will start to populate. This is done through the createContact method available on the ContactList class. Again, you need to cast the resulting objects to the proper type. The createContact method returns a contact, but again you've chosen to use the more specialized version of BlackBerryContact instead. Because this is all being executed on a BlackBerry handheld, you can always cast a contact to a BlackBerryContact safely. The same is true for each of the Java specialized classes and their corresponding BlackBerry specialized class. BlackBerryContact newContact1 = (BlackBerryContact) contacts. createContact();BlackBerryContact newContact1 = (BlackBerryContact) contacts. createContact(); The next segment of code sets the name attribute of the newly created contacts. Notice that this is done through an array of String objects instead of individual methods. This isn't something that is done to be more efficient, it is done this way because it must be; there is no other way. We mentioned before about each field in a PIMItem having a type associated with it. Most of the field types are basic String or Date type fields, but NAME is more complicated than most of the other fields. The NAME field is defined as a StringArray because there are many parts to a name and you want to be able to set each part separately. There aren't very many fields of this type used, but this is probably one of the most important. You can only set the NAME field as a whole unit, so if only one part of the name needs to be changed the entire name field must be replaced. To work with the name, you must first create a string array of the proper size. There is no constant value for this as it may vary with the SDK version. Instead, you must first get the size by using the stringArraySize method on the ContactList and then construct a new array by using the returned value. String[] names = new String[contacts.stringArraySize(BlackBerryContact.NAME)]; Once you have an array of the proper size each part of the name is set by indexing the array by using the NAME constant from the Contact class. names[BlackBerryContact.NAME_FAMILY] = "Smith";names[BlackBerryContact.NAME_GIVEN] = "John"; In this example, you also want to add another name part but are not sure whether the field is supported in this system. Not all fields are supported and not all of the name subfields are supported either. You can test to see whether a field or a subfield is supported by using the isSupportedField or isSupportedArrayElement methods in the ContactList class. In this case, you test to see if the suffix is supported, and then set the suffix if so. if (contacts.isSupportedArrayElement(Contact.NAME, Contact.NAME_SUFFIX)){ names[BlackBerryContact.NAME_SUFFIX]="Jr";} This step is very important if you want to use the same code for multiple platforms. Each system can support the fields it chooses. In this case, the suffix is NOT supported and if you were to step through this code in the debugger, you would see that the code to set the suffix is skipped over. Later on, when you test this application, you will also see that the suffix was not added to the contact. Other platforms may implement it differently. You could just assume each of the name subfields are supported and set the field without testing to see if it is supported. In the BlackBerry SDK, unsupported fields are just quietly ignored. This can lead to confusion wondering why a field doesn't appear in the Address Book application, but it won't cause an error. The next step is to actually add the NAME field to the contact. Up until this time you've simply been building an array in memory with all of the proper values. newContact1.addStringArray( BlackBerryContact.NAME, BlackBerryContact.ATTR_NONE, names); Notice that the method addStringArray doesn't give any indication about what field is being added, but only what type of data is being added. All of the PIMItem methods are like this. Remember, this class is designed to be generic. The first parameter is the field indicator, which is one of the many constants that are defined in the Contact class. In this case, we use the BlackBerryContact class. Because BlackBerryContact derived from Contact, all of the constant values are accessible. The BlackBerryContact class does define some constants that are BlackBerry-specific, such as PIN. For this field you must reference the constant value from BlackBerryContact because the Java standard Contact class does not define it. Partly for this reason, I suggest always referencing constant values from BlackBerryContact because all of the constant values will be available through this class. The method addStringArray was chosen because that is the type of data that you are adding. The NAME field is defined as a string array and so you must use the addStringArray method because it corresponds to the data type of the field. Once you finish with the first contact, the code starts building the NAME string array to add a second contact. For demonstration sake, all of the constant values that are referenced are done so using the Contact class instead of the BlackBerryContact class. names[Contact.NAME_FAMILY] = "Doe";names[Contact.NAME_GIVEN] = "John";if (contacts.isSupportedArrayElement(Contact.NAME, Contact.NAME_PREFIX)){ names[Contact.NAME_PREFIX] = "Dr.";}newContact2.addStringArray(Contact.NAME, Contact.ATTR_NONE, names); Also, notice that the second contact applies a prefix to the name and tests to see if it is supported in the same way as you did for the suffix when adding the previous contact. However, the prefix is supported and if you were to step through this method in the debugger, you would see that the prefix is being set properly. The last step you have to do is to commit the data that has been added to the contact. newContact1.commit();newContact2.commit(); Simply creating a new contact is not enough; you must commit the changes in it by using the commit method. Creating a contact and then never committing it will not have any effect on the Address Book application. It simply won't be shown in the list. That's the whole point of this exercise, so you have to make sure and commit the changes once they are all done. At this point, if you were to run the application and select the menu, you would see two new contacts added to the Address Book application in the simulator. They would show up as Dr. John Doe and John Smith. There would be only names with these contacts because that is all that you've added so far. In the example code that you just stepped through there was one mistake that could have proven to be very serious. Did you catch it? You are reusing the names array to set the names of both contacts. This is actually risky, but it happens to work out in this case. If the SUFFIX field had been supported then your Dr. John Doe would have actually been Dr. John Doe Jr. because the array was not reset before it was used again. If you had changed the order around, John Smith would have been Dr. John Smith. This might have lead to a bug that could have been tough to track down, so keep it in mind.
Read more
  • 0
  • 0
  • 1037

article-image-creating-your-first-blackberry-project
Packt
23 Jul 2010
14 min read
Save for later

Creating your First BlackBerry Project

Packt
23 Jul 2010
14 min read
(For more resources on BlackBerry, see here.) So, without any further words, let's get to work! Choosing the SDK version Remember that the first step is to choose the SDK version to use. For this project we want to choose the lowest possible SDK version, which is 4.2.1. This is because this application is so simple that it will not need to use any of the newer features of more recent versions of the SDK. By choosing a lower version, more models of handheld can be used to run this application. Conversely, choosing a higher SDK version means that fewer models of handhelds can run the application. Therefore, you should choose the lowest version of the SDK that still supports the features you require in order to support as many devices as possible. We will go through the steps of actually applying this later on, but for now, the choice is made and we are ready to move on. Creating a new project You need to create a new project for your new application. The IDE makes it very simple to get started, but because you are creating a BlackBerry project you have to be careful. Let's get started and see what I mean. Time for action – creating a new project You can create a new project by clicking on File | New | Project... option in the menu bar (not the File | Java Project menu item). The New Project dialog gives you many choices for which type of project to create. You want to create a BlackBerry project, of course. Expand the BlackBerry folder in the tree and then select the BlackBerry Project node. When that is done click on the Next button. Enter TipCalc as the name of the application and click on the Finish button to create the new project. What just happened? These three steps are all that is needed to create a BlackBerry project in Eclipse. You were told earlier that choosing New | Java Project was not the right thing to do. This is because the wizard that you get from choosing this menu item is the Swiss Army Knife wizard that will set up any kind of project for Eclipse. It is powerful, complicated, and not for beginners. Because of this, we just won't use it at all. The BlackBerry Project option is much easier to use, you just have to remember to use the New | Project... option instead of the New | Java Project option. Once you have chosen the right menu item, the New Project dialog is shown. Apparently, it is possible to have so many project types available that finding the one you want can be a challenge. The text field at the top of the dialog will filter the tree below to include only projects whose name matches the filter test. In our case though, the BlackBerry project is right near the top and easily accessible so there really isn't a need for the search feature. The last step of the wizard prompts you to enter the name of your new application. Project names are used as a directory name but are not used in code so they can have some special characters, such as a space, which would otherwise be invalid for code. If you try to provide a name that is invalid the wizard will show a warning about the name to indicate the name is not valid. Below the Project name text box is a checkbox indicating to use the default workspace location. By leaving the box checked the new project will be placed in a directory named after the project name under the directory set as the workspace. You can change the location where the new project files are stored by unchecking the Default location checkbox and then entering a new location in the edit field provided. Adding a package to the new project Next, you will create a new package for the application to use. A Java package is a container for the objects in your application and is used to prevent conflicts if the classes you create happen to have the same name as another class in the same project or even the system classes. Packages are equivalent to namespaces in C# and Visual Basic .NET (VB.NET). Adding a package to the project in this way is a minor housekeeping task, but is also an overall good technique because it forces you to choose your package name up front before creating any code. In Java, the naming convention for a package is to use your Internet domain name in reverse—almost like you were creating a new server. In this case, we will use the package name com.rimdev.demo.tipcalc. The package name can be any valid Java name and doesn't have to follow these conventions. Time for action – creating a new project Add the package by right-clicking on the src folder in the Package Explorer and then selecting New | Package. After selecting the menu the New Java Package wizard is shown. This small wizard is here only to collect the folder where the package files will be and the name of the package itself. Because you selected the src folder to begin with, that part is already filled in so you need to specify only the name of the package. Enter the package name com.rimdev.demo.tipcalc into the Name field and then click on Finish to create the package. What just happened? At this point you have an empty project that is ready to start being used. You've taken the BlackBerry application project that you had before and added a package to the src directory in preparation for creating the actual source files (which will come next). The project tree is expanded slightly to include the package you just created under the src directory—the directory whose icon looks like a little mail parcel. Creating a package in your project doesn't result in any actual source files being created. Instead, it sets up the project so that when you do create files later on they will be created with package definitions already included in them. Start at the beginning Every application must have a starting point, and for BlackBerry applications it is at a method named main. The use of the name main goes all the way back to the C programming language, if not further. At that time, simply making a method named main was enough to be able to run an application. However, because Java is an object-oriented language, you can't just make a method named main. In Java, all methods must be in a class, and this includes the method main as well. In addition to the main method all BlackBerry applications must contain an object derived from Application as well. As both the Application-derived class and the main method are required, it is standard practice to include the main method in the same class as your Application. Application and UiApplication As we just said, every BlackBerry application must contain a class derived from Application. The Application class contains the bare essentials for interacting with the BlackBerry operating system. If an application displays a User Interface (UI) then the bare essentials in the Application class are not enough. Instead, you should use UiApplication—the derived class that handles the special processing needed to interact with the user as well as the operating system. So, the next step is to create a class derived from UiApplication and that contains the main method to serve as the starting point of your BlackBerry application. Time for action – adding the UiApplication class To create this starting class right-click on the package you just created in the project and select New | Class. First, give the class a name; enter TipCalcApplication into the Name field. The next step is to set the superclass for your new class. The superclass is another name for a base class, or the class from which your new class will be derived. Eclipse offers a strong browser tool to quickly and easily find the class. Click on the Browse button next to the Superclass field . This dialog is aware of all of the classes in the libraries and allows you to choose the proper one. By default, the class java.lang.Object is set as the superclass. Replace java.lang.Object with uiapplication. Notice that as you do so, other class names appear in the list below, but once it is completely entered only the net.rim.device.api."ui.UiApplication" class is shown. Also notice that even though you entered the name in lowercase and did not enter the complete package name, the filter found the correct class with the correct casing. Click on OK to select this class. Back at the New Java Class dialog there is one more setting to make and that is to check the public static void main(String args[]) option. This creates a stub main function that is used to initiate the application. Use this checkbox only when creating UiApplication objects ; no other classes need them. Check the public static void main(String[] args) checkbox so the wizard will generate the main function. Finally, click on Finish and see the new class in the project. What just happened? You just created the first class for use in your new application! Well, to be more accurate you used Eclipse to set up a new class with some standard elements based on how you filled out the dialog. You could have done the same thing by simply creating a new file and manually adding all of the code by hand, but that's just not as interesting, is it? To be real though, the tools that Eclipse provides are truly helpful and easy to use. The New Java Class dialog that is displayed has many options that can be set and which will cause Eclipse to generate different code. Notice that the package name has already been supplied in the dialog because we started creating this class by right-clicking on the package name in the project. Also, the Source Folder is properly set already because you created the package inside the src folder previously. A closer look at the code Now, let's look at the code that was generated. package com.rimdev.demos.tipcalc;import net.rim.device.api.ui.UiApplication;public class TipCalcApplication extends UiApplication { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub }} The first line of code is the package declaration for com.rimdev.demos.tipcalc. This line defines the package where the TipCalcApplication class will reside. The package can be specified in the New Class dialog but because we previously added the package to the project, the package was supplied automatically to the new New Class dialog. package com.rimdev.demos.tipcalc; The next line is an import statement for net.rim.device.api.ui.UiApplication. Import statements are similar to .NET using or imports statements and declare which libraries are being used. The Java convention is to specifically import each class being referenced. It is possible to wildcard the import statement though, in which case the class name would be replaced with *, that is, net.rim.device.api.ui.*. When doing this all of the classes in that package will be imported into your application and this can make coding easier. It can certainly be annoying having to go back each time you want to use a new class and add the import statement for it. Eclipse is pretty smart and shouldn't include any classes unless they are actually being used when it compiles your application, so there shouldn't be any negative impact on performance. Having said all that, the established convention is not to use wildcarding because it also makes it less clear for someone looking at your application later on to know exactly which classes are being used. In the end, it is probably best to stay with the established convention, which we will do in this article. import net.rim.device.api.ui.UiApplication; Next, we have the class declaration itself. Again, notice that the extends keyword is already added and the class chosen to be the superclass, UiApplication, is added as well. These are added because we chose the UiApplication to be the superclass in the New Class dialog. public class TipCalcApplication extends UiApplication { Lastly, notice that the public static void main method is also created. Remember that every application must have a main method, and this is that method. The method was added because we checked the checkbox for it. Very simple and easy! The words public and static are special keywords that allow the main method to be called by the system before any of the objects in your application are created. public static void main(String[] args) { // TODO Auto-generated method stub} Time for action – expanding TipCalcApplication Now that you have the class created with some of the boilerplate code it's time to expand it and make the application actually do something. You can start off by giving the static main function something to do. Replace the main method with the following code. /** * @param args */public static void main(String[] args) { // TODO Auto-generated method stub // Create a new instance of the application. TipCalcApplication theApp = new TipCalcApplication(); // To make the application enter the event thread and startprocessing messages, // we invoke the enterEventDispatcher() method. theApp.enterEventDispatcher();} Secondly, you need to add the TipCalcApplication constructor to the class so add the following code. private TipCalcApplication(){ // Push the main screen instance onto the UI stack forrendering. pushScreen(new TipCalcMainScreen());} What just happened? The code that you just added takes the simple generated code that you got from the New Class wizard and expands it to set up and start the application. The first thing you did was to put some code in the initially empty main method. This code in the main function is used to actually create an instance of the application's object, which happens to contain the main method. This may seem strange unless you are used to it and understand what the static keyword means. If not, then just understand that static means that the main method can be called without an instance of the object that contains it. You still do need to create an instance of the application though, and so that's the first step. theApp = new TipCalcApplication(); The next line of code in the main method is the call to the enterEventDispatcher method on the application that you just created. This is a method already implemented in the UiApplication class. It does all of the setup necessary to get the application started, runs the application, and waits until the application is finished. theApp.enterEventDispatcher(); As we said earlier, an Application object is required, but it's the main function that is the actual entry point of the program. When the main function is exited the application is terminated and cleaned up by the operating system. The Application object, and more specifically the call to enterEventDispatcher, is why a class derived from Application is required. The last thing to do for this class is to create the constructor and show the first screen. We haven't created the screen yet, but we can go ahead and create the code to use it. The constructor is also very simple and does only one thing. You could do more in the setup and initialization of things in the application constructor of course (if your application needs it), but this simple application does not. Here we create a new instance of the TipCalcMainScreen class and then push it onto the UI stack. The TipCalcMainScreen is the class that you will create next and is the screen that you will display to the user. We will come back to pushScreen and the UI Stack later. pushScreen(new TipCalcMainScreen());
Read more
  • 0
  • 0
  • 1334
Banner background image
Unlock access to the largest independent learning library in Tech for FREE!
Get unlimited access to 7500+ expert-authored eBooks and video courses covering every tech area you can think of.
Renews at €14.99/month. Cancel anytime