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
Explore 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-building-mobile-games-craftyjs-and-phonegap-part-1
Robi Sen
18 Mar 2015
7 min read
Save for later

Building Mobile Games with Crafty.js and PhoneGap: Part 1

Robi Sen
18 Mar 2015
7 min read
In this post, we will build a mobile game using HTML5, CSS, and JavaScript. To make things easier, we are going to make use of the Crafty.js JavaScript game engine, which is both free and open source. In this first part of a two-part series, we will look at making a simple turn-based RPG-like game based on Pascal Rettig’s Crafty Workshop presentation. You will learn how to add sprites to a game, control them, and work with mouse/touch events. Setting up To get started, first create a new PhoneGap project wherever you want in which to do your development. For this article, let’s call the project simplerpg. Figure 1: Creating the simplerpg project in PhoneGap. Navigate to the www directory in your PhoneGap project and then add a new director called lib. This is where we are going to put several JavaScript libraries we will use for the project. Now, download the JQuery library to the lib directory. For this project, we will use JQuery 2.1. Once you have downloaded JQuery, you need to download the Crafty.js library and add it to your lib directory as well. For later parts of this series,you will want to be using a web server such as Apache or IIS to make development easier. For the first part of the post, you can just drag-and-drop the HTML files into your browser to test, but later, you will need to use a web browser to avoid Same Origin Policy errors. This article assumes you are using Chrome to develop in. While IE or FireFox will work just fine, Chrome is used in this article and its debugging environment. Finally, the source code for this article can be found here on GitHub. In the lessons directory, you will see a series of index files with a listing number matching each code listing in this article. Crafty PhoneGap allows you to take almost any HTML5 application and turn it into a mobile app with little to no extra work. Perhaps the most complex of all mobile apps are videos. Video games often have complex routines, graphics, and controls. As such, developing a video game from the ground up is very difficult. So much so that even major video game companies rarely do so. What they usually do, and what we will do here, is make use of libraries and game engines that take care of many of the complex tasks of managing objects, animation, collision detection, and more. For our project, we will be making use of the open source JavaScript game engine Crafty. Before you get started with the code, it’s recommended to quickly review the website here and review the Crafty API here. Bootstrapping Crafty and creating an entity Crafty is very simple to start working with. All you need to do is load the Crafty.js library and initialize Crafty. Let’s try that. Create an index.html file in your www root directory, if one does not exist; if you already have one, go ahead and overwrite it. Then, cut and paste listing 1 into it. Listing 1: Creating an entity <!DOCTYPE html> <html> <head></head> <body> <div id="game"></div> <script type="text/javascript" src="lib/crafty.js"></script> <script> // Height and Width var WIDTH = 500, HEIGHT = 320; // Initialize Crafty Crafty.init(WIDTH, HEIGHT); var player = Crafty.e(); player.addComponent("2D, Canvas, Color") player.color("red").attr({w:50, h:50}); </script> </body> </html> As you can see in listing 1, we are creating an HTML5 document and loading the Crafty.js library. Then, we initialize Crafty and pass it a width and height. Next, we create a Crafty entity called player. Crafty, like many other game engines, follows a design pattern called Entity-Component-System or (ECS). Entities are objects that you can attach things like behaviors and data to. For ourplayerentity, we are going to add several components including 2D, Canvas, and Color. Components can be data, metadata, or behaviors. Finally, we will add a specific color and position to our entity. If you now save your file and drag-and-drop it into the browser, you should see something like figure 2. Figure 2: A simple entity in Crafty.  Moving a box Now,let’s do something a bit more complex in Crafty. Let’s move the red box based on where we move our mouse, or if you have a touch-enabled device, where we touch the screen. To do this, open your index.html file and edit it so it looks like listing 2. Listing 2: Moving the box <!DOCTYPE html> <html> <head></head> <body> <div id="game"></div> <script type="text/javascript" src="lib/crafty.js"></script> <script> var WIDTH = 500, HEIGHT = 320; Crafty.init(WIDTH, HEIGHT); // Background Crafty.background("black"); //add mousetracking so block follows your mouse Crafty.e("mouseTracking, 2D, Mouse, Touch, Canvas") .attr({ w:500, h:320, x:0, y:0 }) .bind("MouseMove", function(e) { console.log("MouseDown:"+ Crafty.mousePos.x +", "+ Crafty.mousePos.y); // when you touch on the canvas redraw the player player.x = Crafty.mousePos.x; player.y = Crafty.mousePos.y; }); // Create the player entity var player = Crafty.e(); player.addComponent("2D, DOM"); //set where your player starts player.attr({ x : 10, y : 10, w : 50, h : 50 }); player.addComponent("Color").color("red"); </script> </body> </html> As you can see, there is a lot more going on in this listing. The first difference is that we are using Crafty.background to set the background to black, but we are also creating a new entity called mouseTracking that is the same size as the whole canvas. We assign several components to the entity so that it can inherit their methods and properties. We then use .bind to bind the mouse’s movements to our entity. Then, we tell Crafty to reposition our player entity to wherever the mouse’s x and y position is. So, if you save this code and run it, you will find that the red box will go wherever your mouse moves or wherever you touch or drag as in figure 3.    Figure 3: Controlling the movement of a box in Crafty.  Summary In this post, you learned about working with Crafty.js. Specifically, you learned how to work with the Crafty API and create entities. In Part 2, you will work with sprites, create components, and control entities via mouse/touch.  About the author Robi Sen, CSO at Department 13, is an experienced inventor, serial entrepreneur, and futurist whose dynamic twenty-plus-year career in technology, engineering, and research has led him to work on cutting edge projects for DARPA, TSWG, SOCOM, RRTO, NASA, DOE, and the DOD. Robi also has extensive experience in the commercial space, including the co-creation of several successful start-up companies. He has worked with companies such as UnderArmour, Sony, CISCO, IBM, and many others to help build new products and services. Robi specializes in bringing his unique vision and thought process to difficult and complex problems, allowing companies and organizations to find innovative solutions that they can rapidly operationalize or go to market with.
Read more
  • 0
  • 0
  • 5763

article-image-cocos2d-iphone-adding-layers-and-making-simple-pause-screen
Packt
30 Dec 2010
6 min read
Save for later

Cocos2d for iPhone: Adding Layers and Making a Simple Pause Screen

Packt
30 Dec 2010
6 min read
Adding more layers to scenes As we have discussed before, a scene can contain any number of layers you want. Well, as long as performance is not an issue. As CCLayer inherits from CCNode, it can be added as the child of CCScenes or other CCLayers, allowing you to organize your content in a nice fashion. There are three types of CCLayers that you can use and combine in your games. They are as follows: CCLayer: We have been using them forever. Besides all the features inherited from CCNodes, they can receive touches and accelerometer input. CCColorLayer: They inherit from CCLayer so besides being able to receive touches and accelerometer input, their opacity and RGB colors can be changed. CCMultiplexLayer: It inherits from CCLayer and can have many children, but only one will be active at any given time. You can switch between those children. In the following examples, we will be creating some CCLayers in different ways to achieve different results. Time for action – creating a HUD to display lives and the score We will begin by building a simple Heads Up Display (HUD) for our game. Its purpose is to show some useful data about the current state of the game to the player. The idea behind making the HUD into a new layer is to simplify the logic of the GameLayer. This way, the GameLayer will only handle stuff of the game itself while leaving the HUD logic to the HUDLayer. In our game, the HUD will display the remaining lives, score, remaining bombs, and anything you want to display later. Once it is done, all we need to do in the GameLayer is send a message so the HUDLayer gets updated. The first step in creating the HUD is to add a new file to the project. In the Xcode project, select File | New file and add a new Objective-C class. Rename it as HUDLayer. Replace the contents of the HudLayer.h with the following lines: #import <Foundation/Foundation.h> #import "cocos2d.h" #import "GameScene.h" @interface HudLayer : CCLayer { CCBitmapFontAtlas * level; CCBitmapFontAtlas * score; CCBitmapFontAtlas * bombs; NSMutableArray * lives; } @property (nonatomic,retain) CCBitmapFontAtlas * level; @property (nonatomic,retain) CCBitmapFontAtlas * score; @property (nonatomic,retain) CCBitmapFontAtlas * bombs; @property (nonatomic,retain) NSMutableArray * lives; @end Do the same with the contents of the HudLayer.m file: #import "HudLayer.h" @implementation HudLayer @synthesize lives,bombs,score,level; - (id) init { if ((self = [super init])) { CCSprite * background = [CCSprite spriteWithFile:@"hud_background.png"]; [background setPosition:ccp(160,455)]; [self addChild:background]; lives = [[NSMutableArray arrayWithCapacity:3]retain]; for(int i=0;i<3;i++) { CCSprite * life = [CCSprite spriteWithFile:@"hud_life.png"]; [life setPosition:ccp(18+ 28*i,465)]; [self addChild:life]; [lives addObject:life]; } CCSprite * bomb = [CCSprite spriteWithFile:@"hud_bomb.png"]; [bomb setPosition:ccp(18,445)]; [self addChild:bomb]; GameLayer * gl = (GameLayer *)[self.parent getChildByTag:KGameLayer]; level = [CCBitmapFontAtlas bitmapFontAtlasWithString:@"Level 1" fntFile:@"hud_font.fnt"]; [level setAnchorPoint:ccp(1,0.5)]; [level setPosition:ccp(310,465)]; [level setColor:ccBLACK]; [self addChild:level]; score = [CCBitmapFontAtlas bitmapFontAtlasWithString:@"Score 0" fntFile:@"hud_font.fnt"]; [score setAnchorPoint:ccp(1,0.5)]; [score setPosition:ccp(310,445)]; [score setColor:ccBLACK]; [self addChild:score]; bombs = [CCBitmapFontAtlas bitmapFontAtlasWithString:@"X3" fntFile:@"hud_font.fnt"]; [bombs setAnchorPoint:ccp(1,0.5)]; [bombs setPosition:ccp(47,440)]; [bombs setColor:ccBLACK]; [self addChild:bombs]; } return self; } - (void) dealloc { [super dealloc]; [lives release]; } @end You can find the images and the font used above in the companion files at Support. What we have to do now is load this new layer and add it as a child of the GameScene. Change the init method of the GameScene class to look like the following: - (id) init { self = [super init]; if (self != nil) { [self addChild:[GameLayer node] z:0 tag:KGameLayer]; //kGameLayer defined in the GameScene.h file. #define kGameLayer 1 [self addChild:[HudLayer node] z:1 tag:KHudLayer]; //kHudLayer defined in the GameScene.h file. #define kHudLayer 2 } return self; } The only thing missing now is to make some changes here and there to be able to update the HUDLayer with the actual state of the game. Let's update the score and remaining lives, for now. Change the loseLife method of the GameLayer class: -(void)loseLife { self.lives--; HudLayer * hl = (HudLayer *)[self.parent getChildByTag:KHudLayer]; CCSprite * live = [hl.lives objectAtIndex:self.lives]; [live setVisible:NO]; if(self.lives ==0) { [self resetGame]; //LOSE THE GAME //GO TO GAME OVER LAYER } } Add the resetGame method: -(void)resetGame { HudLayer * hl = (HudLayer *)[self.parent getChildByTag:KHudLayer]; for(CCSprite * c in hl.lives) { [c setVisible:YES]; } self.level=1; [hl.level setString:@"Level 1"]; self.score=0; [hl.score setString:@"Score 0"]; self.bombs =3; [hl.bombs setString:@"X3"]; lives = STARTING_LIVES; } These methods will handle the displaying of the remaining lives. Finally, modify the Enemy class's destroy method, so it updates the score label instead of logging the score to the console: -(void)destroy { [self reset]; [theGame setScore:theGame.score+100]; HudLayer * hl = (HudLayer *)[theGame.parent getChildByTag:KHudLayer]; [hl.score setString:[NSString stringWithFormat:@"Score %d",theGame.score]]; } Run the game. You should see a HUD at the top of the screen (as shown in the following screenshot) with all the actual information about the state of the game. Destroy some enemies to see the score updated and lose some lives to see the "lives" icons disappear. What just happened? We just went through the steps needed to create a new layer, adding it to the scene and updating its contents. Our new layer just holds some information of the game state and displays it to the player. In order to achieve that we just added a few CCSprites and CCBitmapFontAtlases which get updated when needed. Once the HudLayer class was created we added it to the GameScene over the GameLayer, so its contents are always shown on top of the GameLayer's ones. We also provided a tag for both layers, as we will need to access them from other places. We could also have added a reference to the other layer inside them. That is all what we need to do in order to add more layers to a scene. The rest of the code just handles the updating of the contents of the HudLayer. When the player hits an enemy, a score is awarded. Then the label placed in the HUD is updated. When the hero is hit and a life is lost, we just turn the corresponding icon's visibility off, then when the game is reset we turn all of them on.
Read more
  • 0
  • 0
  • 5759

article-image-sprites
Packt
24 Jun 2014
6 min read
Save for later

Sprites

Packt
24 Jun 2014
6 min read
The goal of this article is to learn how to work with sprites and get to know their main properties. After reading this article, you will be able to add sprites to your games. In this article, we will cover the following topics: Setting up the initial project Sprites and their main properties Adding sprites to the scene Adding sprites as a child node of another sprite Manipulating sprites (moving, flipping, and so on) Performance considerations when working with many sprites Creating spritesheets and using the sprite batch node to optimize performance Using basic animation Creating the game project We could create many separate mini projects, each demonstrating a single Cocos2D aspect, but this way we won't learn how to make a complete game. Instead, we're going to create a game that will demonstrate every aspect of Cocos2D that we learn. The game we're going to make will be about hunting. Not that I'm a fan of hunting, but taking into account the material we need to cover and practically use in the game's code, a hunting game looks like the perfect candidate. The following is a screenshot from the game we're going to develop. It will have several levels demonstrating several different aspects of Cocos2D in action: Time for action – creating the Cocohunt Xcode project Let's start creating this game by creating a new Xcode project using the Cocos2D template, just as we did with HelloWorld project, using the following steps: Start Xcode and navigate to File | New | Project… to open the project creation dialog. Navigate to the iOS | cocos2d v3.x category on the left of the screen and select the cocos2d iOS template on the right. Click on the Next button. In the next dialog, fill out the form as follows: Product Name: Cocohunt Organization Name: Packt Publishing Company Identifier: com.packtpub Device Family: iPhone Click on the Next button and pick a folder where you'd like to save this project. Then, click on the Create button. Build and run the project to make sure that everything works. After running the project, you should see the already familiar Hello World screen, so we won't show it here. Make sure that you select the correct simulator version to use. This project will support iPhone, iPhone Retina (3.5-inch), iPhone Retina (4-inch), and iPhone Retina (4-inch, 64-bit) simulators, or an actual iPhone 3GS or newer device running iOS 5.0 or higher. What just happened? Now, we have a project that we'll be working on. The project creation part should be very similar to the process of creating the HelloWorld project, so let's keep the tempo and move on. Time for action – creating GameScene As we're going to work on this project for some time, let's keep everything clean and tidy by performing the following steps: First of all, let's remove the following files as we won't need them: HelloWorldScene.h HelloWorldScene.m IntroScene.h IntroScene.m We'll use groups to separate our classes. This will allow us to keep things organized. To create a group in Xcode, you should right-click on the root project folder in Xcode, Cocohunt in our case, and select the New Group menu option (command + alt + N). Refer to the following sceenshot: Go ahead and create a new group and name it Scenes. After the group is created, let's place our first scene in it. We're going to create a new Objective-C class called GameScene and make it a subclass of CCScene. Right-click on the Scenes group that we've just created and select the New File option. Right-clicking on the group and selecting New File instead of using File | New | File will place our new file in the selected group after creation. Select Cocoa Touch category on the left of the screen and the Objective-C class on the right. Then click on the Next button. In the next dialog, name the the class as GameScene and make it a subclass of the CCScene class. Then click on the Next button. Make sure that you're in the Cocohunt project folder to save the file and click on the Create button. You can create the Scenes folder while in the save dialog using New Folder button and save the GameScene class there. This way, the hierarchy of groups in Xcode will match the physical folders hierarchy on the disk. This is the way I'm going to do this so that you can easily find any file in the book's supporting file's projects. However, the groups and files organization within groups will be identical, so you can always just open the Cocohunt.xcodeproj project and review the code in Xcode. This should create the GameScene.h and GameScene.m files in the Scenes group, as you can see in the following screenshot: Now, switch to the AppDelegate.m file and remove the following header imports at the top: #import "IntroScene.h" #import "HelloWorldScene.h" It is important to remove these #import directives or we will get errors as we removed the files they are referencing. Import the GameScene.h header as follows: #import "GameScene.h" Then find the startScene: method and replace it with following: -(CCScene *)startScene { return [[GameScene alloc] init]; } Build and run the game. After the splash screen, you should see the already familiar black screen as follows: What just happened? We've just created another project using the Cocos2D template. Most of the steps should be familiar as we have already done them in the past. After creating the project, we removed the unneeded files generated by the Cocos2D template, just as you will do most of the time when creating a new project, since most of the time you don't need those example scenes in your project. We're going to work on this project for some time and it is best to start organizing things well right away. This is why we've created a new group to contain our game scene files. We'll add more groups to the project later. As a final step, we've created our GameScene scene and displayed it on the screen at the start of the game. This is very similar to what we did in our HelloWorld project, so you shouldn't have any difficulties with it.
Read more
  • 0
  • 0
  • 5747

article-image-building-hello-world-application
Packt
29 Oct 2013
6 min read
Save for later

Building a Hello World application

Packt
29 Oct 2013
6 min read
(For more resources related to this topic, see here.) The Hello World application In the previous sections, we saw how to set up environments for development of Sencha Touch. Now let's start with the Hello World application. First of all, create a new folder in your web server and name it sencha-touch-start. Create a subfolder lib inside this folder. In this folder, we will store our Sencha Touch resources. Create two more subfolders inside the lib folder and name them js and css respectively. Copy the sencha-touch-all.js file from the SDK, which we had downloaded, to the lib/js folder. Copy the sencha-touch.css file from SDK to the lib/css folder. Now, create a new file in the sencha-touch-start folder, name it index.html, and add the following code snippet to it: <!DOCTYPE html><html><head><meta charset="utf-8"><title>Hello World</title><script src = "lib/js/sencha-touch-all.js" type="text/javascript"></script><link href="lib/css/sencha-touch.css" rel="stylesheet"type="text/css" /></head><body></body></html> Now create a new file in the sencha-touch-start folder, name it app.js, and add the following code snippet to it: Ext.application({name: 'Hello World',launch: function () {var panel = Ext.create('Ext.Panel', {fullscreen: true,html: 'Welcome to Sencha Touch'});Ext.Viewport.add(panel);}}); Add a link to the app.js file in the index.html page; we created the following link to sencha-touch-all.js and sencha-touch.css: <script src = "app.js" type="text/javascript"></script> Here in the code, Ext.application({..}) creates an instance of the Ext.Application class and initializes our application. The name property defines the name of our application. The launch property defines what an application should do when it starts. This property should always be set to a function inside which we will add our code to initialize the application. Here in this function, we are creating a panel with Ext.create and adding it to Ext.Viewport. Ext. Viewport is automatically created and initialized by the Sencha Touch framework. This is like a base container that holds other components of the application. At this point, your application folder structure should look like this: Now run the application in the browser and you should see the following screen: If your application does not work, please check your web server. It should be turned on, and the steps mentioned earlier should be repeated. Now we will go through some of the most important features and configurations of Sencha Touch. These are required to build real-time Sencha Touch applications. Introduction to layouts Layouts give a developer a number of options to arrange components inside the application. Sencha Touch offers the following four basic layouts: fit hbox vbox card hbox and vbox layouts arrange items horizontally and vertically, respectively. Let's modify our previous example by adding hbox and vbox layouts to it. Modify the code in the launch function of app.js as follows: var panel = Ext.create('Ext.Panel', {fullscreen: true,layout: 'hbox',items: [{xtype: 'panel',html: 'BOX1',flex: 1,style: {'background-color': 'blue'}},{xtype: 'panel',html: 'BOX2',flex: 1,style: {'background-color': 'red'}},{xtype: 'panel',html: 'BOX3',flex: 1,style: {'background-color': 'green'}}]});Ext.Viewport.add(panel); In the preceding code snippet, we specified the layout for a panel by setting the layout: 'hbox' property, and added three items to the panel. Another important configuration to note here is flex. The flex configuration is unique to the hbox and vbox layouts. It controls how much space the component will take up, proportionally, in the overall layout. Here, we have specified flex : 1 to all the child containers; that means the height of the main container will be divided equally in a 1:1:1 ratio among all the three containers. For example, if the height of the main container is 150 px, the height of each child container would be 50 px. Here, the height of the main container would be dependent on the browser width. So, it will automatically adjust itself. This is how Sencha Touch adaptive layout works; we will see this in detail in later sections. If you run the preceding code example in your browser, you should see the following screen: Also, we can change the layout to vbox by setting layout: 'vbox', and you should see the following screen: When we specify a fit layout, a single item will automatically expand to cover the whole space of the container. If we add more than one item and specify only the fit layout, only the first item would be visible at a time. The card layout arranges items in a stack of cards and only one item will be visible at a time, but we can switch between items using the setActiveItem function. We will see this in detail in a later section. Panel – a basic container We have already mentioned the word "panel" in previous examples. It's a basic container component of the Sencha Touch framework. It's basically used to hold items and arrange them in a proper layout by adding the layout configuration. Besides this, it is also used as overlays. Overlays are containers that float over your application. Overlay containers can be positioned relative to some other components. Create another folder in your web server, name it panel- demo, and copy all the files and folders from the sencha-touch-start folder of the previous example. Modify the title in the index.html file. <title>Panel Demo</title> Modify app.js as follows: Ext.application({name: 'PanelDemo',launch: function () {var panel = Ext.create('Ext.Panel', {fullscreen: true,items: [{xtype: 'button',text: 'Show Overlay',listeners: {tap: function(button){var overlay = Ext.create('Ext.Panel', {height: 100,width: 300,html: 'Panel asOverlay'});overlay.showBy(button);}}}]});Ext.Viewport.add(panel);}}); In the preceding code snippet, we have added button as the item in the panel and added listeners for the button. We are binding a tap event to a function for the button. On the tap of the button, we are creating another panel as an overlay and showing it using overlay. showBy(button). Summary This article thus provided us with details on building a Hello World application, which gave you further introduction to the most used components and features of Sencha Touch in real-time applications. Resources for Article : Further resources on this subject: Creating a Simple Application in Sencha Touch [Article] Sencha Touch: Layouts Revisited [Article] Sencha Touch: Catering Form Related Needs [Article]
Read more
  • 0
  • 0
  • 5679

article-image-article-decider-external-apis
Packt
11 Jun 2013
22 min read
Save for later

The Decider: External APIs

Packt
11 Jun 2013
22 min read
(For more resources related to this topic, see here.) Using an external API APIs are provided as a service from many different companies. This is not an entirely altruistic move on the part of the company. The expectation is that by providing the information and access to the company's data, the company gets more usage for their service and more customers. With this in mind, most (if not all) companies will require you to have an account on their system in order to access their API. This allows you to access their systems and information from within your application, but more importantly from the company's perspective, it allows them to maintain control over how their data can be used. If you violate the company's usage policies, they can shut off your application's access to the data, so play nice. The API key Most APIs require a key in order to use them. An API key is a long string of text that gets sent as an extra parameter on any request you send to the API. The key is often composed of two separate pieces and it uniquely identifies your application to the system much like a username and a password would for a regular user account. As such it's also a good idea to keep this key hidden in your application so that your users can't easily get it. While each company is different, an API key is typically a matter of filling out a web form and getting the key. Most companies do not charge for this service. However, some do limit the usage available to outside applications, so it's a good idea to look at any restrictions the company sets on their service. Once you have an API key you should take a look at the available functions for the API. API functions API functions typically come in two types – public and protected: The public functions can simply be requested with the API key The protected functions will also require that a user be logged into the system in order to make the request If the API function is protected, your application will also need to know how to log in correctly with the remote system. The login functions will usually be a part of the API or a web standard such as Facebook and Google's OAuth. It should be noted that while OAuth is a standard, its implementation will vary depending on the service. You will need to consult the documentation for the service you are using to make sure that the features and functions you need are supported. Be sure to read through the service's API documentation to understand which functions you will need and if they require a login. Another thing to understand about APIs is that they don't always do exactly what you need them to do. You may find that you need to do a little more work than you expect to get the data you need. In this case, it's always good to do a little bit of testing. Many APIs offer a console interface where you can type commands directly into the system and examine the results: Image This can be really helpful for digging into the data, but consoles are not always available for every API service. Another option is to send the commands in your application (along with your API credentials) and examine the data returned in the Safari console. The drawback of this method is that the data is often returned as a single-line string that is very difficult to read as shown in the screenshot: Image This is where a tool like JSONLint comes in handy. You can copy and paste the single-line string from your Safari console into the page at http://jsonlint.com and have the string formatted so that it is much easier to read and validate the string as JSON at the same time: Image Once you get a hold of what data is being sent and received, you will need to set it all up in Sencha Touch. External APIs and Sencha Touch As we have talked about earlier in the book, you cannot use a standard AJAX request to get data from another domain. You will need to use a JSONP proxy and store to request data from an external API. Using the API or the Safari console, you can get a good idea of the data that is coming back to you and use it to set up your model. For this example, let's use a simple model called Category. code We can then set up a store to load data from the API: This will set up a store with our Category model and call the url property for our external API. Remember that we have to send our credentials along with the request so we set these as extraParams on the proxy section. The apiKey and appSecret properties shown here are examples. You will need your own API key information to use an API. We also need to set a property called rootProperty in the reader section. Most API's send back a ton of detailed information along with the request and the store needs some idea of where to start loading in the category records. We can also add additional parameters later by calling the setExtraParam() function on our store proxy. This will let us add additional parameters to be sent to our external API URL. Please note that setExtraParam() will add an additional parameter but setExtraParams() will replace all of our extraParams with the new values. The basic application The Decider application is designed to use a combination of local storage, Google's Map API, and the Foursquare API. The application will take a list of people and their food preferences, and then use Foursquare and Google Maps to find nearby places to eat that will match everyone's food preferences. This screenshot provides a pictorial representation of the preceding explanation: Image Our contacts and categories will be stored using local storage. External APIs from Google and Foursquare will generate our maps and restaurant listings respectively. We will start with a quick overview of the basic application structure and forms, before diving into the store setup and API integration. Our main container is a simple card layout: code In this viewport we will add two cards: a navigation view and a form panel. Our navigationvew will serve as our main window for display. We will add additional containers to it via our controller: code This mainView contains our navigationBar and our homeScreen container with the big Get Started button. This button will add new containers to the navigation view (we will look at this later in the controller). A DataStage project stores jobs and define their environment, such as their security and execution resources. Your project, as well as your user account, is typically created by your DataStage administrator. The second item that is added to our viewport is our form panel. This will contain text fields for first and last name, as well as a selectable list for our different food categories: code We close out the form with a segmentedbutton property, which has options for Save and Cancel. We will add the handler functions for these buttons later on in our controller. We also include a title bar at the top of the form to give the user some idea of what they are doing. One of the key pieces of this form is the categories list, so let's take a closer look at how it works. Creating the categories list Since we will be getting our list of potential restaurants from the Foursquare API, we need to use their categories as well so that we can match things up with some degree of accuracy. The Foursquare API can be found at https://developer.foursquare.com/. As mentioned before, you will need a Foursquare account to access the API. You will also need an API key in order to integrate Foursquare with your application. We can use the Foursquare's API to get a list of categories, however the API returns a list of a few hundred categories including Airports, Trains, Taxis, Museums, and Restaurants. Additionally, each of these has its own subcategories. All we really want is the subcategories for Restaurants. To make things more complicated, Foursquare's API also returns the data like this: code This means we can only get at a specific category by its order in the array of categories. For example, if Restaurants is the twenty-third category in the array, we can get to it as: categories[23], but we cannot get to it by calling categories['Restaurants']. Unfortunately, if we use categories[23] and Foursquare adds a new category or changes the order, our application will break. This is a situation where it pays to be adaptable. Foursquare's API includes a console where we can try out our API requests. We can use this console to request the data for all of our categories and then pull the data we need into a flat file for our application. Check this URL to see the output: https://developer.foursquare.com/docs/explore#req=venues/categories We can copy just the Restaurant information that we need from categories and save this as a file called categories.json and call it from our store. A better solution to this conundrum would be to write some server code that would request the full category list from Foursquare and then pull out just the information we are interested in. But for the sake of brevity, we will just use a flat json file. Each of our categories are laid out like this: code The main pieces we care about are the id, name, shortname and icon values. This gives us a data model that looks like this: code Notice that we also add a function to create an image URL for the icons we need. We do this with the convert configuration, which lets us assemble the data for image URL based on the other data in the record: code The convert function is automatically passed both the data value (v), which we ignore in this case, and the record (rec), which lets us create a valid Foursquare URL by combining the icon.prefix value, a number, and the icon.suffix value in our record. If you take a look at our previous category data example, this would yield a URL of: https://foursquare.com/img/categories_v2/food/argentinian_32.png By changing the number we can control the size of the icon (this is part of the Foursquare API as well). We combine this with our XTemplate: code This gives us a very attractive list for choosing our categories: Images Next we need to take a look at the controller for the contact form. Creating the contact controller The contact controller handles saving the contact and canceling the action. We start out the controller by declaring our references and controls: code Remember that our refs (references) provide a handy shortcut we can use anywhere in the controller to get to the pieces we need. Our control section attaches tap listeners to our cancel and save buttons. Next we need to add our two functions after the controls section. The doCancel function is really simple: code We just use our references to clear the contact editor, deselect all the items in our category list, and switch back to our main view. The save function is a little more complex, but similar to the functions we have covered elsewhere in this book: code As with our previous save functions, we create a new MyApp.model.Contact and add the values from our form. However, since our list isn't really a standard form component we need to grab its selections separately and add them to the contact data as a comma-separated list. We do this by creating an empty array and using Ext.each() to loop through and run a function on all our categories. We then use join to implode the array into a comma-separated list. Finally, we save the contact and run our doCancel function to clean up and return to our main view. Now that we can add contacts we need to create a controller to handle our requests to the Foursquare and Google APIs, and get the data back to our users. Integrating with Google Maps and Foursquare Our application still has a couple of tasks to accomplish. It needs to: Handle the click of the Get Started button Add our maps panel and offer to adjust the current location via Google Maps API Display a list of friends to include in our search Display the search results in a list Display the details for a selected result We will start out with the basic skeleton of the controller, create the views and stores, and then finish up the controller to complete the application. Starting the mainView.js controller We will start the mainView.js controller file with some placeholders for the stores. We will add views later on and some references for those components. Keep in mind that when working with placeholders in this fashion the application will not be testable until all the files are actually in place. We create the mainView.js file in our controllers folder: code At the top of this configuration we require Ext.DateExtras. This file provides us with formatting options for date objects. If this file is not included, only the now() method for date objects will be available in your application. In our views section we have added placeholders for confirmLocation, restaurantList, friendChooser,and restaurantDetails. We will add these files later on, along with the RestaurantStore file listed in our stores section. We also have a number of references for these views, stores, and some of their sub-components. We will need to create these views before getting to the rest of our controller. We will take these views in the order the user will see them, starting with the confirmLocation view. Creating the confirmLocation view The confirmLocation view first appears when the user clicks on the Get Started button. This view will present the user with a map showing their current location and offer an option to switch to a different location if the user desires. The following screenshot gives a pictorial representation of the preceding code: Image In order to give ourselves a bit more flexibility, we will be using the Google Maps Tracker plugin as part of this view. You can find this plugin in your Sencha Touch 2 folder in examples/map/lib/plugin/google/Tracker.js. Copy the file into a lib/google folder in your main application folder and be sure to add it into the requires section of your app.js file: code This plugin will let us easily drop markers on the map. Once the Google Tracker plugin file is included in the application, we can set up our confirmLocation.js view like so: code The view itself is a simple container with some HTML at the top asking the user to confirm their location. Next we have a map container that uses our Google Tracker plugin to configure the map and animate the location marker to drop from the top of the screen to the current location of the user. The position configuration is a default location, which is used when the user denies the application access to their current location. This one is set to the Sencha Headquarters. Next we need a few options for the user to choose from: Cancel, New Location, and Next. We will add these as a segmented button under our map container. We add the code to the end of our items container (after the map container): code Each of our buttons has an associated action. This allows us to assign functions to each button within the mainView.js controller. By creating buttons in this fashion, we maintain separation between the display of the application and the functionality of the application. This is really helpful when you want to re-use a view component. The next view the user encounters is the Friends Chooser. Creating the Friends Chooser view The friendsChooser.js file uses a similar list to our previous category chooser. This lets our users select multiple people to include in the restaurant search: Image Our friendChooser extends the Ext.Container component and allows the user to select from a list of friends: code As with our previous panel, we have a container with HTML at the top to provide some instructions to the user. Below that is our list container, which, like our category list, allows for selection of multiple items via the mode: 'MULTI' configuration. We also set grouped to true. This allows our store to group the contacts together by last name. If you take a look at the ContactStore.js file, you can see where we do: code This configuration returns the first letter of the last name for grouping. The last thing we need to do with our friendChooser.js file is add the buttons at the bottom to Cancel or Finish the search. The buttons go out in the items section, just below the list: code As in our previous view, we use a segmentedbutton property with actions assigned to each of our individual buttons. Once the user clicks on Finish, we will need to return a list of restaurants they can select from. Creating the restaurant list, store, and details Our restaurant list will use a store and the Foursquare API to return a list of restaurants based on the shared preferences of everyone the user selected. The following screenshot exemplifies the preceding explanation: Image This component is pretty basic: code This component uses a simple list with a configuration option for onItemDisclosure:true. This places an arrow next to the restaurant name in the list. The user will be able to click on the arrow and see the details for that restaurant (which we will create after the store). We also set grouped to true, only this time our store will use a function to calculate and sort by distance. Creating the restaurant store and model The restaurant store is where we set up our request to the Foursquare API: code The RestaurantStore.js file sets a model and storeId field for our store and then defines our proxy. The proxy section is where we set up our request to Foursquare. As we mentioned at the start of the article, this needs to be a jsonp request since it is going to another domain. We make our request to https://api.foursquare. com/v2/venues/search and we are looking for the responses.venues section of the JSON array that gets returned. You will note that this store currently has no other parameters to send to Foursquare. We will add these later on in the controller before we load the store. For the model, we can consult the Foursquare API documentation to see the information that is returned for a restaurant (called a venue in Foursquare terms) at https://developer.foursquare.com/docs/responses/venue You can include any of the fields listed on the page. For this app, we have chosen to include the following code in our model: code You can add more fields if you want to display more information in the details view. Creating the details view The details view is a simple panel and XTemplate combination. Using our controller, the panel will receive the data record when a user clicks on a restaurant in the list: code Since the tpl tag is basically HTML, you can use any CSS styling you like here. Keep in mind that certain fields such as contact, location, and categories can have more than one entry. You will need to use <tpl for="fieldname"> to loop through these values. Now that the views are complete, we need to head back to our controller and add the functions to put everything together. Finishing the main view controller When we started out with our main controller, we added all of our views, stores, and references. Now it's time to add the functionality for the application. We start by adding a control section to the end of our config: code The controls are based on the references in the controller and they add functions to specific listeners on the component. These are each in the format of: code Once these controls are in place, we can add our functions after the config section of our controller. Our first function is doStart. This function loads our Contacts store and checks to see if we have any existing contacts. If not, we alert the user and offer to let them add some. If they have contacts we create a new instance of our confirmLocation container and push it onto the main navigation view: code Remember that since the mainView is a navigation view, a Back button will automatically be created in the top toolbar. This function will show the user our initial map panel with the users current location. This panel needs four functions: one to cancel the request, one to pop up a new location window, one to set the new location, and one to move on to the next step: code We actually want to be able to use the doCancel function from anywhere in the process. As we add new panels to our mainView navigation, these panels simply pile up in a stack. This means we need to get the number of panels currently on the mainView stack. We use length-1 to always leave the initial panel (the one with our big Get Started button) on the stack. We use pop to remove all but the first panel from the stack. This way the Cancel button will take us all the way back to the beginning of our stack, while the Back button will take us back just to the previous step. The next function is doNewLocation(), which uses Ext.Msg.prompt to ask the user to enter a new location: code If the user enters a new location, we call setNewLocation to process the text the user entered in the prompt textbox: code This code gets our map and encodes the text the user passed us as a geocode location. If Google returns a valid address, we center the map on the location and drop a marker to show the exact location. We also set the latitude and longitude so that we can reference them later. If we fail to get a valid address, we alert the user so they can fix it and try again. Once the user is happy with the location they can click on the Next button, which fires our doChooseFriends function: This function pushes our friendchooser view onto the stack for display. The friendchooser view allows the user to select multiple friends and click on Cancel or Finish. Since we have already taken care of our Cancel button with our doCancel function, we just need to write the doShowRestaurants function. This function starts by looping through the selected friends. For the first one in the list, we grab the restaurant categories we have stored for the friend and convert it from a comma-separated list (which is how we stored it) into an array. This lets us grab every subsequent selection and run Ext.Array.intersect() to find the common categories between all of the selected friends: code Next, we load the store based on the common categories by categoryID, the location data we have stored in our map, client_id, and client_secret that comprise our API key for Foursquare and a radius value (in meters). We also send a required field called v that is set to the current date. Finally, we push our restaurant list component onto the stack of containers. This will display our list of results and allow the user to click on for details. This brings us to our doShowRestaurantDetails function: code When the user taps one of the disclosure icons in our list of restaurants, we push a restaurantdetails view onto the stack of containers and set its data to the record that was tapped. This displays the details for the restaurant in our details XTemplate Homework There are a number of additional features that can be added to this type of application, including: Editing for contacts (or automatically pulling friends from Facebook) Setting up a live feed for the categories menu Adding additional venues other than restaurants Combining the application with additional APIs such as Yelp for reviews Just remember the key requirements of using additional APIs: the API key(s), studying the API documentation, and using the JSONP store for grabbing the data. Summary In this article we talked about using external APIs to enhance your Sencha Touch applications. This included: An overview of API basics Putting together the basic application Interaction with Google Maps and Foursquare Building the views, models, and stores Building the application controller Resources for Article : Further resources on this subject: How to Use jQuery Mobile Grid and Columns Layout [Article] iPhone JavaScript: Installing Frameworks [Article] An Introduction to Rhomobile [Article]
Read more
  • 0
  • 0
  • 5524

article-image-working-local-and-remote-data-sources
Packt
02 Nov 2015
9 min read
Save for later

Working With Local and Remote Data Sources

Packt
02 Nov 2015
9 min read
In this article by Jason Kneen, the author of the book Appcelerator Titanium Smartphone Application Development Cookbook - Second Edition, we'll cover the following recipes: Reading data from remote XML via HTTPClient Displaying data using a TableView Enhancing your TableViews with custom rows Filtering your TableView with the SearchBar control Speeding up your remote data access with Yahoo! YQL and JSON Creating a SQLite database Saving data locally using a SQLite database Retrieving data from a SQLite database Creating a "pull to refresh" mechanism in iOS (For more resources related to this topic, see here.) As you are a Titanium developer, fully understanding the methods available for you to read, parse, and save data is fundamental to the success of the apps you'll build. Titanium provides you with all the tools you need to make everything from simple XML or JSON calls over HTTP, to the implementation of local relational SQL databases. In this article, we'll cover not only the fundamental methods of implementing remote data access over HTTP, but also how to store and present that data effectively using TableViews, TableRows, and other customized user interfaces. Prerequisites You should have a basic understanding of both the XML and JSON data formats, which are widely used and standardized methods of transporting data across the Web. Additionally, you should understand what Structured Query Language (SQL) is and how to create basic SQL statements such as Create, Select, Delete, and Insert. There is a great beginners' introduction to SQL at http://sqlzoo.net if you need to refer to tutorials on how to run common types of database queries. Reading data from remote XML via HTTPClient The ability to consume and display feed data from the Internet, via RSS feeds or alternate APIs, is the cornerstone of many mobile applications. More importantly, many services that you may wish to integrate into your app will probably require you to do this at some point or the other, so it is vital to understand and be able to implement remote data feeds and XML. Our first recipe in this article introduces some new functionality within Titanium to help facilitate this need. Getting ready To prepare for this recipe, open Titanium Studio, log in and create a new mobile project. Select Classic and Default Project. Then, enter MyRecipes as the name of the app, and fill in the rest of the details with your own information, as you've done previously. How to do it... Now that our project shell is set up, let's get down to business! First, open your app.js file and replace its contents with the following: // this sets the background color of the master View (when there are no windows/tab groups on it) Ti.UI.setBackgroundColor('#000'); // create tab group var tabGroup = Ti.UI.createTabGroup(); var tab1 = Ti.UI.createTab({ icon:'cake.png', title:'Recipes', window:win1 }); var tab2 = Ti.UI.createTab({ icon:'heart.png', title:'Favorites', window:win2 }); // // add tabs // tabGroup.addTab(tab1); tabGroup.addTab(tab2); // open tab group tabGroup.open(); This will get a basic TabGroup in place, but we need two windows, so we create two more JavaScript files called recipes.js and favorites.js. We'll be creating a Window instance in each file to do this we created the window2.js and chartwin.js files. In recipes.js, insert the following code. Do the same with favorites.js, ensuring that you change the title of the Window to Favorites: //create an instance of a window module.exports = (function() { var win = Ti.UI.createWindow({ title : 'Recipes', backgroundColor : '#fff' }); return win; })(); Next, go back to app.js, and just after the place where TabGroup is defined, add this code: var win1 = require("recipes"); var win2 = require("favorites"); Open the recipes.js file. This is the file that'll hold our code for retrieving and displaying recipes from an RSS feed. Type in the following code at the top of your recipes.js file; this code will create an HTTPClient and read in the feed XML from the recipe's website: //declare the http client object var xhr = Ti.Network.createHTTPClient(); function refresh() { //this method will process the remote data xhr.onload = function() { console.log(this.responseText); }; //this method will fire if there's an error in accessing the //remote data xhr.onerror = function() { //log the error to our Titanium Studio console console.log(this.status + ' - ' + this.statusText); }; //open up the recipes xml feed xhr.open('GET', 'http://rss.allrecipes.com/daily.aspx?hubID=79'); //finally, execute the call to the remote feed xhr.send(); } refresh(); Try running the emulator now for either Android or iPhone. You should see two tabs appear on the screen, as shown in the following screenshot. After a few seconds, there should be a stack of XML data printed to your Appcelerator Studio console log. How it works… If you are already familiar with JavaScript for the Web, this should make a lot of sense to you. Here, we created an HTTPClient using the Ti.Network namespace, and opened a GET connection to the URL of the feed from the recipe's website using an object called xhr. By implementing the onload event listener, we can capture the XML data that has been retrieved by the xhr object. In the source code, you'll notice that we have used console.log() to echo information to the Titanium Studio screen, which is a great way of debugging and following events in our app. If your connection and GET request were successful, you should see a large XML string output in the Titanium Studio console log. The final part of the recipe is small but very important—calling the xhr object's send() method. This kicks off the GET request; without it, your app would never load any data. It is important to note that you'll not receive any errors or warnings if you forget to implement xhr.send(), so if your app is not receiving any data, this is the first place to check. If you are having trouble parsing your XML, always check whether it is valid first! Opening the XML feed in your browser will normally provide you with enough information to determine whether your feed is valid or has broken elements. Displaying data using a TableView TableViews are one of the most commonly used components in Titanium. Almost all of the native apps on your device utilize tables in some shape or form. They are used to display large lists of data in an effective manner, allowing for scrolling lists that can be customized visually, searched through, or drilled down to expose child views. Titanium makes it easy to implement TableViews in your application, so in this recipe, we'll implement a TableView and use our XML data feed from the previous recipe to populate it with a list of recipes. How to do it... Once we have connected our app to a data feed and we're retrieving XML data via the XHR object, we need to be able to manipulate that data and display it in a TableView component. Firstly, we will need to create an array object called data at the top of our refresh function in the recipes.js file; this array will hold all of the information for our TableView in a global context. Then, we need to disseminate the XML, read in the required elements, and populate our data array object, before we finally create a TableView and set the data to be our data array. Replace the refresh function with the following code: function refresh() { var data = []; //empty data array //declare the http client object var xhr = Ti.Network.createHTTPClient(); //create the table view var tblRecipes = Ti.UI.createTableView(); win.add(tblRecipes); //this method will process the remote data xhr.onload = function() { var xml = this.responseXML; //get the item nodelist from our response xml object var items = xml.documentElement.getElementsByTagName("item"); //loop each item in the xml for (var i = 0; i < items.length; i++) { //create a table row var row = Ti.UI.createTableViewRow({ title: items.item(i).getElementsByTagName("title").item(0).text }); //add the table row to our data[] object data.push(row); } //end for loop //finally, set the data property of the tableView to our //data[] object tblRecipes.data = data; }; //open up the recipes xml feed xhr.open('GET', 'http://rss.allrecipes.com/daily.aspx?hubID=79'); //finally, execute the call to the remote feed xhr.send(); } The following screenshot shows the TableView with the titles of our recipes from the XML feed: How it works... The first thing you'll notice is that we are taking the response data, extracting all the elements that match the name item, and assigning it to items. This gives us an array that we can use to loop through and assign each individual item to the data array object that we created earlier. From there, we create our TableView by implementing the Ti.UI.createTableView() function. You should notice almost immediately that many of our regular properties are also used by tables, including width, height, and positioning. In this case, we did not specify these values, which means that by default, the TableView will occupy the screen. A TableView has an extra, and important, property—data. The data property accepts an array of data, the values of which can either be used dynamically (as we have done here with the title property) or be assigned to the subcomponent children of a TableRow. As you begin to build more complex applications, you'll be fully understanding just how flexible table-based layouts can be. Summary In this article, we covered fundamental methods of implementing remote data access over HTTP. As you are a Titanium developer, we had also understand the available methods to build a successful app. More importantly, many services that you may wish to integrate into your app will probably require you to do this at some point or the other, so it is vital to understand and be able to implement remote data feeds and XML Resources for Article: Further resources on this subject: Mobile First Bootstrap [article] Anatomy of a Sprite Kit project [article] Designing Objects for 3D Printing [article]
Read more
  • 0
  • 0
  • 5495
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 €18.99/month. Cancel anytime
article-image-building-iphone-app-using-swift-part-2
Ryan Loomba
29 Oct 2014
5 min read
Save for later

Building an iPhone App Using Swift: Part 2

Ryan Loomba
29 Oct 2014
5 min read
Let’s continue on from Part 1, and add a new table view to our app. In our storyboard, let’s add a table view controller by searching in the bottom right and dragging. Next, let’s add a button to our main view controller that will link to our new table view controller. Similar to what we did with the web view, Ctrl + click on this button and drag it to the newly created table view controller.Upon release, choose push. Now, let’s make sure everything works properly. Hit the large play button and click on Table View. You should now be taken to a blank table: Let’s populate this table with some text. Go to File ->  New ->  File  and choose a Cocoa Touch Class. Let’s call this file TableViewController, and make this a subclass of UITableViewController in the Swift language. Once the file is saved, we’ll be presented with a file with some boilerplate code.  On the first line in our class file, let’s declare a constant. This constant will be an array of strings that will be inserted into our table: let tableArray: NSArray = ["Apple", "Orange", "Banana", "Grape", "Kiwi"] Let’s modify the function that has this signature: func tableView(tableView: UITableView!, numberOfRowsInSection section: Int) -> Int This function returns the number of rows in our table view. Instead of setting this to zero, let’s change this to ten. Next, let’s uncomment the function that has this signature: override func numberOfSectionsInTableView(tableView: UITableView!) -> Int This function controls how many sections we will have in our table view. Let’s modify this function to return 1.  Finally, let’s add a function that will populate our cells: override func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! { let cell: UITableViewCell = UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: "MyTestCell") cell.textLabel.text = tableArray.objectAtIndex(indexPath.row) as NSString return cell }  This function iterates through each row in our table and sets the text value to be equal to the fruits we declared at the top of the class file. The final file should look like this: class TableViewController: UITableViewController { let tableArray: NSArray = ["Apple", "Orange", "Banana", "Grape", "Kiwi"] override func viewDidLoad() { super.viewDidLoad() } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } // MARK: - Table view data source override func numberOfSectionsInTableView(tableView: UITableView!) -> Int { // #warning Potentially incomplete method implementation. // Return the number of sections. return 1 } override func tableView(tableView: UITableView!, numberOfRowsInSection section: Int) -> Int { // #warning Incomplete method implementation. // Return the number of rows in the section. return tableArray.count } override func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! { let cell: UITableViewCell = UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: "MyTestCell") cell.textLabel.text = tableArray.objectAtIndex(indexPath.row) as NSString return cell } } Finally, we need to go back to our storyboard and link to our custom table view controller class. Select the storyboard, click on the table view controller, choose the identity inspector and fill in TableViewController  for the custom class. If we click the play button to build our project and then click on our table view button, we should see our table populated with names of fruit: Adding a map view Click on the Sample Swift App icon in the top left of the screen and then choose Build Phases. Under Link Binary with Libraries, click the plus button and search for MapKit. Once found, click Add: In the story board, add another view controller. Search for a MKMapView and drag it into the newly created controller. In the main navigation controller, create another button named Map View, Ctrl + click + drag to the newly created view controller, and upon release choose push: Additionally, choose the Map View in the storyboard, click on the connections inspector, Ctrl + click on delegate and drag to the map view controller. Next, let’s create a custom view controller that will control our map view. Go to File -> New -> File and choose Cocoa Touch. Let’s call this file MapViewController and inherit from UIViewController. Let’s now link our map view in our storyboard to our newly created map view controller file. In the storyboard, Ctrl + click on the map view and drag to our Map View Controller to create an IBOutlet variable. It should look something like this: @IBOutlet var mapView: MKMapView! Let’s add some code to our controller that will display the map around Apple’s campus in Cupertino, CA. I’ve looked up the GPS coordinates already, so here is what the completed code should look like: import UIKit import MapKit class MapViewController: UIViewController, MKMapViewDelegate { @IBOutlet var mapView: MKMapView! override func viewDidLoad() { super.viewDidLoad() let latitude:CLLocationDegrees = 37.331789 let longitude:CLLocationDegrees = -122.029620 let latitudeDelta:CLLocationDegrees = 0.01 let longitudeDelta:CLLocationDegrees = 0.01 let span:MKCoordinateSpan = MKCoordinateSpan(latitudeDelta: latitudeDelta, longitudeDelta: longitudeDelta) let location:CLLocationCoordinate2D = CLLocationCoordinate2DMake(latitude, longitude) let region: MKCoordinateRegion = MKCoordinateRegionMake(location, span) self.mapView.setRegion(region, animated: true) // Do any additional setup after loading the view. } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } } This should now build, and when you click on the Map View button, you should be able to see a map showing Apple’s campus at the center of the screen.  About the Author Ryan is a software engineer and electronic dance music producer currently residing in San Francisco, CA. Ryan started up as a biomedical engineer but fell in love with web/mobile programming after building his first Android app. You can find him on GitHub @rloomba.
Read more
  • 0
  • 0
  • 5494

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
  • 5456

article-image-iphone-issues-related-calls-sms-and-contacts
Packt
28 Jun 2011
9 min read
Save for later

iPhone: Issues Related to Calls, SMS, and Contacts

Packt
28 Jun 2011
9 min read
  iPhone JavaScript Cookbook Clear and practical recipes for building web applications using JavaScript and AJAX without having to learn Objective-C or Cocoa         Read more about this book       (For more resources related to this subject, see here.) At the time of publication, working with contacts requires us to develop native applications. But we can use JavaScript with the PhoneGap framework for building these kinds of applications for the iPhone. This is the main reason for applying this framework for the recipes included in this article. This article focuses on issues related to calls, SMS, and contacts. We'll learn how to handle contacts and how to send an SMS or place a phone call simply by interacting with the user interface. Calling a number In this recipe, you'll learn how to call a number when a user clicks on a button in the user interface. Specifically, we're going to build a simple list containing our contacts where each represents a person and their phone number. After clicking on one of these elements the dial screen will be opened and the user will only need to click on the green button for calling the specified number. We only need to build a simple XHTML file for this recipe. It can be found at code/ch08/call.html in the code bundle provided on the Packtpub site. Code files can be downloaded at the Packt website. Getting ready This recipe requires the use of the iWebKit framework. How to do it... Open your favorite text editor or IDE and create a new file called call.html. Add the standard XHTML headers and the required lines for invoking the JavaScript and CSS files provided by iWebKit: <link href="../iwebkit/css/style.css" rel="stylesheet media="screen" type="text/css" /> <script src="../iwebkit/javascript/functions.js" type="text/javascript"></script> Add the main HTML code for defining our user interface: <body class="list"> <div id="topbar"> <div id="title">Call</div> </div> <div id="content"> <ul> <li class="title">Contacts</li> <li><a class="noeffect" href="tel:555-666-777"> <span class="name">Aaron Stone</span></a></li> <li><a class="noeffect" href="tel:555-888-999"> <span class="name">Ben Jackson</span></a></li> <li><a class="noeffect" href="tel:555-222-333"> <span class="name">Bob McKenzie</span></a></li> <li><a class="noeffect" href="tel:555-444-666"> <span class="name">Luke Johnson</span></a></li> <li><a class="noeffect" href="tel:555-333-666"> <span class="name">Michael Sterling</span></a></li> </ul> </div> Now, save your new file and load it on your device. The following screenshot shows you the result of loading the file built for this recipe: How it works... The most important part of the code in this recipe is the anchor element inside each <li> tag. The href attribute of the anchor element is using a string, which represents a specific protocol followed by a number. In fact, tel identifies the protocol and the iPhone, understanding its meaning displays the dial screen allowing the user to call a number. On the other hand, the class noeffect was applied to each anchor for opening the dial screen in fullscreen mode. From a strict point of view, iWebkit is not a must for calling numbers. Safari Mobile indentifies the tel protocol by default. However, we used the mentioned framework because it helps us to easily construct a list with many items. What happens if you are using an iOS device other than the iPhone? It is not possible to call numbers from an iPad or iPod touch as of now. The code developed for this recipe works differently in these devices. Instead of calling numbers, iPad and iPod touch will ask you if you want to save numbers in the address book. Sending an SMS to a number The previous recipe explained how you can call a number from your applications. This recipe will show you how to send an SMS to a selected number. For simplicity we're going to use the same approach. We'll develop a simple XHTML file displaying a list with different contacts. When the user clicks on one of the contacts the iPhone will display the screen for sending an SMS. Getting ready As in the previous recipe we will use the iWebKit framework. As both recipes are similar, we're going to use the same XHTML file developed for the previous recipe. How to do it... Open the call.html file and replace the content of the href attribute of each <li>item for a new string starting with sms: instead of tel. For example, the first item will be the following: <li> <a class="noeffect" href="sms:555-666-777"> <span class="name">Aaron Stone</span> </a> </li> Save the new content of the original file as a new file called sms.html, then you'll be ready for testing it on your iPhone. How it works... As you've learned in the previous recipe, Safari Mobile identifies the tel protocol for calling numbers. In the same way, sms is used for sending SMS's. Also for this recipe the iWebKit is used for building the user interface. Selecting contacts Thanks to this recipe we'll learn how to select a contact from the address book of the iPhone and to display its related information. Our goal is quite simple; when the user clicks on a button, a new screen will display all available contacts. After clicking on one of these elements, the complete name of the selected contact will be displayed in the main screen. Although this recipe is very simple, you can apply it for building complex applications that require dealing with contacts available through the address book of the iPhone. The complete code for this recipe can be reached at code/ch08/queryAddress in the code bundle provided on the Packtpub site. Getting ready For this recipe we'll use three different frameworks: PhoneGap, XUI, and UiUIKit. Before continuing, make sure you have these frameworks installed on your machine. Also, remember you'll need a Mac OS X computer with the iOS SDK and Xcode installed. How to do it... The first step is to create a new PhoneGap project through Xcode. After creating your new project, the next step will be to open the main index.html file for adding our own code for this recipe. First, you should add the following lines inside the head section of the mentioned HTML file: <script type="text/javascript" src="xui-2.0.0..min.js"></script> <link rel="stylesheet" href="uiuikit/stylesheets/iphone.css" /> <style type="text/css"> #mybtn { margin-right: 12px; } </style> The next step is to comment out the JavaScript function preventBehavior() and the line below this function. Then, we're going to add our JavaScript code: function searchContact() { navigator.contacts.chooseContact(onSucessContact); } function onSucessContact(contact) { var selectedContact = contact.name; x$('#ul_contacts').html( 'inner', "<li>" + selectedContact + "</li>"); } Finally, we'll modify the original body section adding the following lines of HTML code: <div id="header"> <h1>Contacts</h1> </div> <h1>Working with contacts</h1> <p id="p_btn"> <a href="#" id="mybtn" onclick="searchContact()" class="button white">Select</a> </p> <ul id='ul_contacts'></ul> Before continuing and after applying all changes inside the code, we need to copy some files to the www directory of our project. Specifically, we're going to copy the uiuikit directory and the xui-2.0.0.min.js file. Remember, these components belong to the UiUIKit and XUI framework respectively. Save your project and click on the Build and Run button of Xcode for testing your new application. After loading the application in the iPhone Simulator, you can see a screen similar to next screenshot: When the user clicks on the button Select, a list with all the available contacts will be displayed as shown in the following screenshot: After selecting one of the items showed in the list, our application will display the data for the selected contact: How it works... PhoneGap provides a JavaScript function for accessing the predefined screen of the iPhone for selecting contacts. The name of this function is ChooseContact() and it is invoked through the navigator.contacts predefined object. It encapsulates the access to the address book of the iPhone. As a parameter, this function requires a callback method that will be invoked when a contact is selected. In our case, we implemented a function called onSuccessContact(), which captures the complete name of the contact displaying the result in a simple list. onSuccesContact uses a parameter called contact, which represents an object containing the information related to the selected contact from the address book. The XUI framework allows us to add new items to our ul list by manipulating the DOM of the HTML page. On the other hand, the UiUIKit framework was used for building the user interface for our small application. We used a bit of CSS for centering our button. Actually, we modified the right margin of this widget. The CSS style for this appears before the JavaScript code, also inside the head section.
Read more
  • 0
  • 0
  • 5358

article-image-jquery-mobile-organizing-information-list-views
Packt
23 Jun 2011
8 min read
Save for later

jQuery Mobile: Organizing Information with List Views

Packt
23 Jun 2011
8 min read
jQuery Mobile First Look Discover the endless possibilities offered by jQuery Mobile for rapid Mobile Web Development You might have noticed that the vast majority of websites built using jQuery Mobile have their content laid out in very similar ways; sure, they differ in the design, colors, and overall feel, but they all have a list-based layout. There is a way in which we can organize our information and take advantage of each and every space in the browser: information is displayed vertically, one piece under another. There are no sidebars of any kind and links are organized in lists – for a cleaner and tidy look. But list views are also used to actually be a list of information. Some examples may be lists of albums, names, tasks, and so on: after all, our purpose is to build a mobile web application and the majority of services and pages can be organized in a way which closely resembles a list. Basics and conventions for list views Due to the particular nature of lists, list views are coded exactly the same way a standard HTML unordered list would. After all, the purpose of list views is to organize our information in a tidy way, presenting a series of links which are placed one under another; the easiest way to grasp their usefulness is, in my opinion, imagining a music player application. A music player would need a clean enough interface, listing the artists, albums, and songs by name. In order to play a song, the user would need to select an artist, and then choose the album in which the song he wishes to play has been released. To create our first view (artists), we would use the following code. Make sure you add the data-role="listview" attribute to the unordered list tag: <ul data-role="listview"> <li><a href="astra.html">Astra</a></li> <li><a href="zappa.html">Frank Zappa</a></li> <li><a href="tull.html">Jethro Tull</a></li> <li><a href="radiohead.html">Radiohead</a></li> <li><a href="who.html">The Who</a></li> </ul> The jQuery Mobile framework automatically styles the list elements accordingly, and adds a right arrow icon. List elements fill the full width of the browser window: Whenever an item is selected (click/tap event), jQuery Mobile will parse the code inside the list element and issue an AJAX request for the first URL found. The page (obtained via AJAX) is then inserted into the existing DOM and a page transition event is triggered. The default page transition is a slide-left animation; clicking the back button on the newly displayed page will result in a slide-right animation. Choosing the list type as per your requirements A somewhat large variety of lists are available for us to choose from in order to make use of the type of list view that is best suited to our needs. Below are listed (sorry, no pun intended!) the different types of list views along with a brief description of how to use them and what part of code we need to change in order to obtain a certain list view. Nested lists Bearing in mind that list views elements are based on the standard HTML unordered list element, we might be wondering what would happen if we try and create a second list inside a list view. By nesting a ul element inside list items, jQuery Mobile will adopt a different kind of behavior to our list items. Our first step toward the creation of a nested list is removing any link present in the list item, as a click event will show the nested list instead of redirecting to another page. The child list will be put into a new "page" with the title of the parent in the header. We're now implementing nested list elements into our sample music player interface by changing our markup to the following. This way, we are able to browse artists and albums. Please note that we have removed any links to external pages: <ul data-role="listview"> <li>Astra <ul> <li><a href="astra_weirding.html">The Weirding</a></li> </ul> </li> <li>Frank Zappa <ul> <li><a href="zappa_hotrats.html">Hot Rats</a></li> <li><a href="zappa_yellowshark.html">Yellow Shark</a></li> </ul> </li> <li>Jethro Tull <ul> <li><a href="tull_aqualung.html">Aqualung</a></li> <li><a href="tull_thick.html">Thick as a Brick</a></li> </ul> </li> <li>Radiohead <ul> <li><a href="radiohead_ok.html">OK Computer</a></li> <li><a href="radiohead_rainbows.html">In Rainbows</a></li> <li><a href="radiohead_kol.html">The King of Limbs</a></li> </ul> </li> <li>The Who <ul> <li><a href="who_next.html">Who's Next</a></li> <li><a href="who_q.html">Quadrophenia</a></li> <li><a href="who_tommy.html">Tommy</a></li> </ul> </li> </ul> If we clicked on the Radiohead element, we would then be able to see the following page: By default, child list will be given a Swatch B theme to indicate they are at a secondary level of navigation; we can select a different color swatch by specifying a data-theme attribute on the child list element. We can see the header turned blue, and the artist name is used as the header. We have a choice to go back to the previous page (artists) or click again onto a list item (album) to view more. Numbered lists Our music player interface has reached the point in which we need to list the tracks contained in an album. Of course, tracks have a sequence, and we want to give the user the possibility to see what track number is without having to count them all – and without writing numbers manually, that would be terrible! In a very similar fashion, we can use ordered list elements (ol) to obtain numbering: jQuery Mobile will try to use CSS to display numbers or, if not supported, JavaScript. The following code lists all of the tracks for an album: Note there is no limit to the number of lists you can nest. <ul> <!-- ... --> <li>Radiohead <ul> <li><a href="radiohead_ok.html">OK Computer</a></li> <li><a href="radiohead_rainbows.html">In Rainbows</a></li> <li>The King of Limbs <ol> <li><a href="play.html">Bloom</a></li> <li><a href="play.html">Morning Mr. Magpie</a></li> <li><a href="play.html">Little by Little</a></li> <li><a href="play.html">Feral</a></li> <li><a href="play.html">Lotus Flower</a></li> <li><a href="play.html">Codex</a></li> <li><a href="play.html">Give Up the Ghost</a></li> <li><a href="play.html">Separator</a></li> </ol> </li> </ul> </li> <!-- ... --> </ul>
Read more
  • 0
  • 0
  • 5269
Packt
08 Jul 2015
21 min read
Save for later

To Be or Not to Be – Optionals

Packt
08 Jul 2015
21 min read
In this article by Andrew J Wagner, author of the book Learning Swift, we will cover: What is an optional? How to unwrap an optional Optional chaining Implicitly unwrapped optionals How to debug optionals The underlying implementation of an optional (For more resources related to this topic, see here.) Introducing optionals So, we know that the purpose of optionals in Swift is to allow the representation of the absent value, but what does that look like and how does it work? An optional is a special type that can wrap any other type. This means that you can make an optional String, optional Array, and so on. You can do this by adding a question mark (?) to the type name: var possibleString: String? var possibleArray: [Int]? Note that this code does not specify any initial values. This is because all optionals, by default, are set to no value at all. If we want to provide an initial value, we can do so like any other variable: var possibleInt: Int? = 10 Also note that, if we leave out the type specification (: Int?), possibleInt would be inferred to be of the Int type instead of an Int optional. It is pretty verbose to say that a variable lacks a value. Instead, if an optional lacks a variable, we say that it is nil. So, both possibleString and possibleArray are nil, while possibleInt is 10. However, possibleInt is not truly 10. It is still wrapped in an optional. You can see all the forms a variable can take by putting the following code in to a playground: var actualInt = 10 var possibleInt: Int? = 10 var nilInt: Int? println(actualInt) // "10" println(possibleInt) // "Optional(10)" println(nilInt) // "nil" As you can see, actualInt prints out as we expect it to, but possibleInt prints out as an optional that contains the value 10 instead of just 10. This is a very important distinction because an optional cannot be used as if it were the value it wraps. The nilInt optional just reports that it is nil. At any point, you can update the value within an optional, including the fact that you can give it a value for the first time using the assignment operator (=): nilInt = 2 println(nilInt) // "Optional(2)" You can even remove the value within an optional by assigning it to nil: nilInt = nil println(nilInt) // "nil" So, we have this wrapped form of a variable that may or may not contain a value. What do we do if we need to access the value within an optional? The answer is that we must unwrap it. Unwrapping an optional There are multiple ways to unwrap an optional. All of them essentially assert that there is truly a value within the optional. This is a wonderful safety feature of Swift. The compiler forces you to consider the possibility that an optional lacks any value at all. In other languages, this is a very commonly overlooked scenario that can cause obscure bugs. Optional binding The safest way to unwrap an optional is using something called optional binding. With this technique, you can assign a temporary constant or variable to the value contained within the optional. This process is contained within an if statement, so that you can use an else statement for when there is no value. An optional binding looks like this: if let string = possibleString {    println("possibleString has a value: \(string)") } else {    println("possibleString has no value") } An optional binding is distinguished from an if statement primarily by the if let syntax. Semantically, this code says "if you can let the constant string be equal to the value within possibleString, print out its value; otherwise, print that it has no value." The primary purpose of an optional binding is to create a temporary constant that is the normal (nonoptional) version of the optional. It is also possible to use a temporary variable in an optional binding: possibleInt = 10 if var int = possibleInt {    int *= 2 } println(possibleInt) // Optional(10) Note that an astrix (*) is used for multiplication in Swift. You should also note something important about this code, that is, if you put it into a playground, even though we multiplied int by 2, the value does not change. When we print out possibleInt later, the value still remains Optional(10). This is because even though we made the int variable (otherwise known as mutable), it is simply a temporary copy of the value within possibleInt. No matter what we do with int, nothing will be changed about the value within possibleInt. If we need to update the actual value stored within possibleInt, we need to simply assign possibleInt to int after we are done modifying it: possibleInt = 10 if var int = possibleInt {    int *= 2    possibleInt = int } println(possibleInt) // Optional(20) Now the value wrapped inside possibleInt has actually been updated. A common scenario that you will probably come across is the need to unwrap multiple optional values. One way of doing this is by simply nesting the optional bindings: if let actualString = possibleString {    if let actualArray = possibleArray {        if let actualInt = possibleInt {            println(actualString)            println(actualArray)            println(actualInt)        }    } } However, this can be a pain as it increases the indentation level each time to keep the code organized. Instead, you can actually list multiple optional bindings in a single statement separated by commas: if let actualString = possibleString,    let actualArray = possibleArray,    let actualInt = possibleInt {    println(actualString)    println(actualArray)    println(actualInt) } This generally produces more readable code. This way of unwrapping is great, but saying that optional binding is the safe way to access the value within an optional implies that there is an unsafe way to unwrap an optional. This way is called forced unwrapping. Forced unwrapping The shortest way to unwrap an optional is by forced unwrapping. This is done using an exclamation mark (!) after the variable name when it is used: possibleInt = 10 possibleInt! *= 2   println(possibleInt) // "Optional(20)" However, the reason it is considered unsafe is that your entire program crashes if you try to unwrap an optional that is currently nil: nilInt! *= 2 // fatal error The full error you get is "unexpectedly found as nil while unwrapping an optional value". This is because forced unwrapping is essentially your personal guarantee that the optional truly holds a value. This is why it is called forced. Therefore, forced unwrapping should be used in limited circumstances. It should never be used just to shorten up the code. Instead, it should only be used when you can guarantee, from the structure of the code, that it cannot be nil, even though it is defined as an optional. Even in this case, you should check whether it is possible to use a nonoptional variable instead. The only other place you may use it is when your program truly cannot recover if an optional is nil. In these circumstances, you should at least consider presenting an error to the user, which is always better than simply having your program crash. An example of a scenario where forced unwrapping may be used effectively is with lazily calculated values. A lazily calculated value is a value that is not created until the first time it is accessed. To illustrate this, let's consider a hypothetical class that represents a filesystem directory. It would have a property that lists its contents that are lazily calculated. The code would look something like this: class FileSystemItem {} class File: FileSystemItem {} class Directory: FileSystemItem {    private var realContents: [FileSystemItem]?    var contents: [FileSystemItem] {        if self.realContents == nil {           self.realContents = self.loadContents()        }        return self.realContents!    }      private func loadContents() -> [FileSystemItem] {        // Do some loading        return []    } } Here, we defined a superclass called FileSystemItem that both File and Directory inherit from. The contents of a directory is a list of any kind of FileSystemItem. We define content as a calculated variable and store the real value within the realContents property. The calculated property checks whether there is a value yet loaded for realContents; if there isn't, it loads the contents and puts it into the realContents property. Based on this logic, we know with 100 percent certainty that there will be a value within realContents by the time we get to the return statement, so it is perfectly safe to use forced unwrapping. Nil coalescing In addition to optional binding and forced unwrapping, Swift also provides an operator called the nil coalescing operator to unwrap an optional. This is represented by a double question mark (??). Basically, this operator lets us provide a default value for a variable or operation result in case it is nil. This is a safe way to turn an optional value into a nonoptional value and it would look something like this: var possibleString: String? = "An actual string" println(possibleString ?? "Default String")   // "An Actual String" Here, we ask the program to print out possibleString unless it is nil, in which case, it will just print Default String. Since we did give it a value, it printed out that value and it is important to note that it printed out as a regular variable, not as an optional. This is because one way or another, an actual value will be printed. This is a great tool for concisely and safely unwrapping an optional when a default value makes sense. Optional chaining A common scenario in Swift is to have an optional that you must calculate something from. If the optional has a value you want to store the result of the calculation on, but if it is nil, the result should just be set to nil: var invitee: String? = "Sarah" var uppercaseInvitee: String? if let actualInvitee = invitee {    uppercaseInvitee = actualInvitee.uppercaseString } This is pretty verbose. To shorten this up in an unsafe way, we could use forced unwrapping: uppercaseInvitee = invitee!.uppercaseString However, optional chaining will allow us to do this safely. Essentially, it allows optional operations on an optional. When the operation is called, if the optional is nil, it immediately returns nil; otherwise, it returns the result of performing the operation on the value within the optional: uppercaseInvitee = invitee?.uppercaseString So in this call, invitee is an optional. Instead of unwrapping it, we will use optional chaining by placing a question mark (?) after it, followed by the optional operation. In this case, we asked for the uppercaseInvitee property on it. If invitee is nil, uppercaseInvitee is immediately set to nil without it even trying to access uppercaseString. If it actually does contain a value, uppercaseInvitee gets set to the uppercaseString property of the contained value. Note that all optional chains return an optional result. You can chain as many calls, both optional and nonoptional, as you want in this way: var myNumber: String? = "27" myNumber?.toInt()?.advancedBy(10).description This code attempts to add 10 to myNumber, which is represented by String. First, the code uses an optional chain in case myNumber is nil. Then, the call to toInt uses an additional optional chain because that method returns an optional Int type. We then call advancedBy, which does not return an optional, allowing us to access the description of the result without using another optional chain. If at any point any of the optionals are nil, the result will be nil. This can happen for two different reasons: This can happen because myNumber is nil This can also happen because toInt returns nil as it cannot convert String to the Int type If the chain makes it all the way to advanceBy, there is no longer a failure path and it will definitely return an actual value. You will notice that there are exactly two question marks used in this chain and there are two possible failure reasons. At first, it can be hard to understand when you should and should not use a question mark to create a chain of calls. The rule is that you should always use a question mark if the previous element in the chain returns an optional. However, since you are prepared, let's look at what happens if you use an optional chain improperly: myNumber.toInt() // Value of optional type 'String?' not unwrapped In this case, we try to call a method directly on an optional without a chain so that we get an error. We also have the case where we try to inappropriately use an optional chain: var otherNumber = "10" otherNumber?.toInt() // Operand of postfix '?'   should have optional type Here, we get an error that says a question mark can only be used on an optional type. It is great to have a good sense of catching errors, which you will see when you make mistakes, so that you can quickly correct them because we all make silly mistakes from time to time. Another great feature of optional chaining is that it can be used for method calls on an optional that does not actually return a value: var invitees: [String]? = [] invitee?.removeAll(keepCapacity: false) In this case, we only want to call removeAll if there is truly a value within the optional array. So, with this code, if there is a value, all the elements are removed from it: otherwise, it remains nil. In the end, option chaining is a great choice for writing concise code that still remains expressive and understandable. Implicitly unwrapped optionals There is a second type of optional called an implicitly unwrapped optional. There are two ways to look at what an implicitly unwrapped optional is. One way is to say that it is a normal variable that can also be nil. The other way is to say that it is an optional that you don't have to unwrap to use. The important thing to understand about them is that like optionals, they can be nil, but like a normal variable, you do not have to unwrap them. You can define an implicitly unwrapped optional with an exclamation mark (!) instead of a question mark (?) after the type name: var name: String! Just like with regular optionals, implicitly unwrapped optionals do not need to be given an initial value because they are nil by default. At first, this may sound like it is the best of both worlds, but in reality, it is more like the worst of both worlds. Even though an implicitly unwrapped optional does not have to be unwrapped, it will crash your entire program if it is nil when used: name.uppercaseString // Crash A great way to think about them is that every time an implicitly unwrapped optional is used, it is implicitly performing a forced unwrapping. The exclamation mark is placed in its type declaration instead of using it every time. This is particularly bad because it appears the same as any other variable except for how it is declared. This means that it is very unsafe to use, unlike a normal optional. So, if implicitly unwrapped optionals are the worst of both worlds and are so unsafe, why do they even exist? The reality is that in rare circumstances, they are necessary. They are used in circumstances where a variable is not truly optional, but you also cannot give an initial value to it. This is almost always true in the case of custom types that have a member variable that is nonoptional, but cannot be set during initialization. A rare example of this is a view in iOS. UIKit, as we discussed earlier, is the framework that Apple provides for iOS development. In it, Apple has a class called UIView that is used for displaying content on the screen. Apple also provides a tool in Xcode called Interface Builder that lets you design these views in a visual editor instead of in code. Many views designed in this way need references to other views that can be accessed programmatically later. When one of these views is loaded, it is initialized without anything connected and then all the connections are made. Once all the connections are made, a function called awakeFromNib is called on the view. This means that these connections are not available for use during initialization, but are available once awakeFromNib is called. This order of operations also ensures that awakeFromNib is always called before anything actually uses the view. This is a circumstance where it is necessary to use an implicitly unwrapped optional. A member variable may not be defined until the view is initialized and when it is completely loaded: import UIKit class MyView: UIView {    @IBOutlet var button : UIButton!    var buttonOriginalWidth : CGFloat!      override func awakeFromNib() {        self.buttonOriginalWidth = self.button.frame.size.width    } } Note that we have actually declared two implicitly unwrapped optionals. The first is a connection to button. We know this is a connection because it is preceded by @IBOutlet. This is declared as an implicitly unwrapped optional because the connections are not set up until after initialization, but they are still guaranteed to be set up before any other methods are called on the view. This also then leads us to make our second variable, buttonOriginalWidth, implicitly unwrapped because we need to wait until the connection is made before we can determine the width of button. After awakeFromNib is called, it is safe to treat both button and buttonOriginalWidth as nonoptional. You may have noticed that we had to dive pretty deep in to app development in order to find a valid use case for implicitly unwrapped optionals, and this is arguably only because UIKit is implemented in Objective-C. Debugging optionals We already saw a couple of compiler errors that we commonly see because of optionals. If we try to call a method on an optional that we intended to call on the wrapped value, we will get an error. If we try to unwrap a value that is not actually optional, we will get an error that the variable or constant is not optional. We also need to be prepared for runtime errors that optionals can cause. As discussed, optionals cause runtime errors if you try to forcefully unwrap an optional that is nil. This can happen with both explicit and implicit forced unwrapping. If you followed my advice so far in this article, this should be a rare occurrence. However, we all end up working with third-party code, and maybe they were lazy or maybe they used forced unwrapping to enforce their expectations about how their code should be used. Also, we all suffer from laziness from time to time. It can be exhausting or discouraging to worry about all the edge cases when you are excited about programming the main functionality of your app. We may use forced unwrapping temporarily while we worry about that main functionality and plan to come back to handle it later. After all, during development, it is better to have a forced unwrapping crash the development version of your app than it is for it to fail silently if you have not yet handled that edge case. We may even decide that an edge case is not worth the development effort of handling because everything about developing an app is a trade-off. Either way, we need to recognize a crash from forced unwrapping quickly, so that we don't waste extra time trying to figure out what went wrong. When an app tries to unwrap a nil value, if you are currently debugging the app, Xcode shows you the line that tries to do the unwrapping. The line reports that there was EXC_BAD_INSTRUCTION and you will also get a message in the console saying fatal error: unexpectedly found nil while unwrapping an Optional value:   You will also sometimes have to look at which code currently calls the code that failed. To do that, you can use the call stack in Xcode. When your program crashes, Xcode automatically displays the call stack, but you can also manually show it by going to View | Navigators | Show Debug Navigator. This will look something as follows:   Here, you can click on different levels of code to see the state of things. This becomes even more important if the program crashes within one of Apple's framework, where you do not have access to the code. In that case, you should move up the call stack to the point where your code is called in the framework. You may also be able to look at the names of the functions to help you figure out what may have gone wrong. Anywhere on the call stack, you can look at the state of the variables in the debugger, as shown in the following screenshot:   If you do not see this variable's view, you can display it by clicking on the button at the bottom-left corner, which is second from the right that will be grayed out. Here, you can see that invitee is indeed nil, which is what caused the crash. As powerful as the debugger is, if you find that it isn't helping you find the problem, you can always put println statements in important parts of the code. It is always safe to print out an optional as long as you don't forcefully unwrap it like in the preceding example. As we saw earlier, when an optional is printed, it will print nil if it doesn't have a value or it will print Optional(<value>) if it does have a value. Debugging is an extremely important part of becoming a productive developer because we all make mistakes and create bugs. Being a great developer means that you can identify problems quickly and understand how to fix them soon after that. This will largely come from practice, but it will also come when you have a firm grasp of what really happens with your code instead of simply adapting some code you find online to fit your needs through trial and error. The underlying implementation At this point, you should have a pretty strong grasp of what an optional is and how to use and debug it, but it is valuable to look deeper at optionals and see how they actually work. In reality, the question mark syntax for optionals is just a special shorthand. Writing String? is equivalent to writing Optional<String>. Writing String! is equivalent to writing ImplicitlyUnwrappedOptional<String>. The Swift compiler has shorthand versions because they are so commonly used This allows the code to be more concise and readable. If you declare an optional using the long form, you can see Swift's implementation by holding command and clicking on the word Optional. Here, you can see that Optional is implemented as an enumeration. If we simplify the code a little, we have: enum Optional<T> {    case None    case Some(T) } So, we can see that Optional really has two cases: None and Some. None stands for the nil case, while the Some case has an associated value, which is the value wrapped inside Optional. Unwrapping is then the process of retrieving the associated value out of the Some case. One part of this that you have not seen yet is the angled bracket syntax (<T>). This is a generic and essentially allows the enumeration to have an associated value of any type. Realizing that optionals are simply enumerations will help you to understand how to use them. It also gives you some insight into how concepts are built on top of other concepts. Optionals seem really complex until you realize that they are just two-case enumerations. Once you understand enumerations, you can pretty easily understand optionals as well. Summary We only covered a single concept, optionals, in this article, but we saw that this is a pretty dense topic. We saw that at the surface level, optionals are pretty straightforward. They offer a way to represent a variable that has no value. However, there are multiple ways to get access to the value wrapped within an optional, which have very specific use cases. Optional binding is always preferred as it is the safest method, but we can also use forced unwrapping if we are confident that an optional is not nil. We also have a type called implicitly unwrapped optional to delay the assigning of a variable that is not intended to be optional, but we should use it sparingly because there is almost always a better alternative. Resources for Article: Further resources on this subject: Network Development with Swift [article] Flappy Swift [article] Playing with Swift [article]
Read more
  • 0
  • 0
  • 5063

article-image-android-30-application-development-gps-locations-and-maps
Packt
22 Jul 2011
7 min read
Save for later

Android 3.0 Application Development: GPS, Locations, and Maps

Packt
22 Jul 2011
7 min read
  Android 3.0 Application Development Cookbook Design and develop rich smartphone and tablet applications for Android 3.0         Introduction For managing location based information, Android provides the android.location package which in turn gives us the LocationManager class that gives us access to location based functions such as the latitude and longitude of a device's position. Tracking a device over time is made equally convenient and the LocationListener class monitors changes in location as they occur. Listening for location changes is only a part of the story, as Google provides APIs for managing Google Maps data and displaying and manipulating maps through the use of the MapView and MapController classes. These powerful tools require us to sign up with Google first, and once done enable us to zoom in and out of maps, pan to any location that we are looking for, and when we want to, include application information on a map, and even add our own layers to maps and mark locations on a Google map. Detecting a device's location Android locations are expressed in terms of latitude and longitude coordinates. The default format is degrees. The Location object can also be used to store a time-stamp and other information such as speed and distance traveled. Although obtaining a device's last known location does not always yield the most accurate information, it is often the first reading that we may want. It is fast, simple to employ, and makes a good introduction to the LocationManager. <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> How to do it... Use the TextView provided in the main.xml file and give it a resource ID: android:id="@+id/text_view" Declare a TextView as a class-wide field in the Java activity code: TextView textView; Then, find it in the usual way, from within the onCreate() method: textView = (TextView) findViewById(R.id.text_view); Next, and still within onCreate(), declare and define our LocationManager: LocationManager manager = (LocationManager) getSystemService(Context.LOCATION_SERVICE); Then, to retrieve the last known location using GPS and display this in the text view, add these lines: Location loc = manager.getLastKnownLocation(LocationManager.GPS_PROVIDER); textView.setText("latitude: " + loc.getLatitude() + "nlongitude: " + loc.getLongitude()); Run the code on a handset or emulator to obtain its location: How it works... The use of a LocationManager to obtain the device's last known location is very straightforward. As with other system services, we obtained it with getSystemService() and the getLastKnownLocation() method returns the Location object itself, which can be further queried to provide latitude and longitude coordinates. We could have done more with the Location object, for example Location.getAltitude() will return altitude and getDistance(Location) and getBearing(Location) will return distance and bearing to another Location. It is possible to send mock locations to an emulator using the DDMS perspective in Eclipse: Before sending location data this way, make sure that you have set the emulator to allow mock locations under Settings | Applications | Development. It is worth noting that although use of the getLastKnownLocation() method may not always be accurate, particularly if the device has been switched off for some time, it does have the advantage of yielding almost immediate results. There's more... Using GPS to obtain a location has a couple of drawbacks. Firstly, it does not work indoors; and secondly, it is very demanding on the battery. Location can be determined by comparing cell tower signal strengths, and although this method is not as accurate, it works well indoors and is much more considerate to the device's battery. Obtaining a location with a network provider The network provider is set up in exactly the same way as the previous GPS example, simply exchange the Location declaration with: Location loc = manager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER); You will also need to change, or amend, the permission in the manifest file with: <uses-permission android_name="android.permission.ACCESS_COURSE_LOCATION" /> Listening for location changes Obtaining the last known location as we did in the previous recipe is all well and good and handy for retrieving a Location quickly, but it can be unreliable if the handset has been switched off or if the user is on the move. Ideally we want to be able to detect location changes as they happen and to do this we employ a LocationListener. In this recipe we will create a simple application that keeps track of a mobile device's movements. Getting ready This task can be performed most easily by starting where the previous one left off. If you have not completed that task yet, do so now—it is very short—then return here. If you have already completed the recipe then simply open it up to proceed. How to do it... First, move the declaration of our LocationManager so that it is a class-wide field: LocationManager manager; In the main Java activity code, before the TextView.setText() call, add the following three lines: LocationListener listener = new MyLocationListener(); manager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 30000, 50, listener); Location location = manager.getLastKnownLocation(LocationManager.GPS_PROVIDER); Now create an inner class called MyLocationListener that implements LocationListener: LocationListener: public class MyLocationListener implements LocationListener { } Eclipse will most likely insist that you add some unimplemented methods and you should do so. For now, only complete one of them, the onLocationChanged() callback: @Override public void onLocationChanged(Location l) { textView.setText("/n/nlatitude: " + l.getLatitude() + "nlongitude: " + l.getLongitude()); } Leave the others as they are: @Override public void onProviderDisabled(String provider) {} @Override public void onProviderEnabled(String provider) {} @Override public void onStatusChanged(String provider, int status, Bundle extras) {} If you want to test this code on an emulator, then go right ahead. However, this code will create a serious drain on the battery of a handset, and it is wise to switch our listener off when it is not needed. Here we have used the activity's onPause() and onResume() functions to control this. You may wish to include these statements in any part of your activity's life cycle that suits your application's purpose: @Override protected void onResume() { super.onResume(); manager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 30000, 50, listener); } @Override protected void onPause() { super.onPause(); manager.removeUpdates(this); } If you have not already tested this application, do so now. You will need to move around if you are testing it on a real device, or send mock locations to an emulator to see the code in action: How it works... In this recipe we used the LocationManager to provide location updates roughly every 30 seconds (30000 milliseconds) or whenever the location changed by more than 50 meters. We say 'roughly' because these values work only as a guide and the actual frequency of updates often varies from the values we set. Nevertheless, setting these two parameters of the requestLocationUpdates() method to high values can make a big difference to the amount of battery power the GPS provider consumes. Hopefully the use of the provider and the LocationListener as the other two parameters is self explanatory. The LocationListener operates very much as other listeners do and the purpose of the onProviderEnabled() and onProviderDisabled() should be clear. The onStatusChanged() method is called whenever a provider becomes unavailable after a period of availability or vice versa. The int, status can represent 0 = OUT_OF_SERVICE, 1 = TEMPORARILY_UNAVAILABLE, or 2 = AVAILABLE.  
Read more
  • 0
  • 0
  • 4961

article-image-adding-graphics-map
Packt
13 Feb 2014
4 min read
Save for later

Adding Graphics to the Map

Packt
13 Feb 2014
4 min read
(For more resources related to this topic, see here.) Graphics are points, lines, or polygons that are drawn on top of your map in a layer that is independent of any other data layer associated with a map service. Most people associate a graphic object with the symbol that is displayed on a map to represent the graphic. However, each graphic in ArcGIS Server can be composed of up to four objects, including the geometry of the graphic, the symbology associated with the graphic, attributes that describe the graphic, and an info template that defines the format of the info window that appears when a graphic is clicked on. Although a graphic can be composed of up to four objects, it is not always necessary for this to happen. The objects you choose to associate with your graphic will be dependent on the needs of the application that you are building. For example, in an application that displays GPS coordinates on a map, you may not need to associate attributes or display info window for the graphic. However, in most cases, you will be defining the geometry and symbology for a graphic. Graphics are temporary objects stored in a separate layer on the map. They are displayed while an application is in use and are removed when the session is complete. The separate layer, called the graphics layer, stores all the graphics associated with your map. Just as with the other types of layers, GraphicsLayer also inherits from the Layer class. Therefore, all the properties, methods, and events found in the Layer class will also be present in GraphicsLayer. Graphics are displayed on top of any other layers that are present in your application. An example of point and polygon graphics is provided in the following screenshot. These graphics can be created by users or drawn by the application in response to the tasks that have been submitted. For example, a business analysis application might provide a tool that allows the user to draw a freehand polygon to represent a potential trade area. The polygon graphic would be displayed on top of the map, and could then be used as an input to a geoprocessing task that pulls demographic information pertaining to the potential trade area. Many ArcGIS Server tasks return their results as graphics. The QueryTask object can perform both attribute and spatial queries. The results of a query are then returned to the application in the form of a FeatureSet object, which is simply an array of features. You can then access each of these features as graphics and plot them on the map using a looping structure. Perhaps you'd like to find and display all land parcels that intersect the 100 year flood plain. A QueryTask object could perform the spatial query and then return the results to your application, where they would then be displayed as polygon graphics on the map. In this article, we will cover the following topics: The four parts of a graphic Creating geometry for graphics Symbolizing graphics Assigning attributes to graphics Displaying graphic attributes in an info window Creating graphics Adding graphics to the graphics layer The four parts of a graphic A graphic is composed of four items: Geometry, Symbol, Attributes, and InfoTemplate, as shown in the following diagram: A graphic has a geometric representation that describes where it is located. The geometry, along with a symbol, defines how the graphic is displayed. A graphic can also have attributes that provide descriptive information about the graphic. Attributes are defined as a set of name-value pairs. For example, a graphic depicting a wildfire location could have attributes that describe the name of the fire along with the number of acres burned. The info template defines what attributes should be displayed in the info window that appears when the graphic appears, along with how they should be displayed. After their creation, the graphic objects must be stored inside a GraphicsLayer object, before they can be displayed on the map. This GraphicsLayer object functions as a container for all the graphics that will be displayed. All the elements of a graphic are optional. However, the geometry and symbology of a graphic are almost always assigned. Without these two items, there would be nothing to display on the map, and there isn't much point in having a graphic unless you're going to display it. The following figure shows the typical process of creating a graphic and adding it to the graphics layer. In this case, we are applying the geometry of the graphic as well as a symbol to depict the graphic. However, we haven't specifically assigned attributes or an info template to this graphic.
Read more
  • 0
  • 0
  • 4951
Packt
18 Jan 2013
7 min read
Save for later

New Connectivity APIs – Android Beam

Packt
18 Jan 2013
7 min read
(For more resources related to this topic, see here.) Android Beam Devices that have NFC hardware can share data by tapping them together. This could be done with the help of the Android Beam feature. It is similar to Bluetooth, as we get seamless discovery and pairing as in a Bluetooth connection. Devices connect when they are close to each other (not more than a few centimeters). Users can share pictures, videos, contacts, and so on, using the Android Beam feature. Beaming NdefMessages In this section, we are going to implement a simple Android Beam application. This application will send an image to another device when two devices are tapped together. There are three methods that are introduced with Android Ice Cream Sandwich that are used in sending NdefMessages. These methods are as follows: setNdefPushMessage() : This method takes an NdefMessage as a parameter and sends it to another device automatically when devices are tapped together. This is commonly used when the message is static and doesn't change. setNdefPushMessageCallback() : This method is used for creating dynamic NdefMessages. When two devices are tapped together, the createNdefMessage() method is called. setOnNdefPushCompleteCallback() : This method sets a callback which is called when the Android Beam is successful. We are going to use the second method in our sample application. Our sample application's user interface will contain a TextView component for displaying text messages and an ImageView component for displaying the received images sent from another device. The layout XML code will be as follows: <RelativeLayout android_layout_width="match_parent" android_layout_height="match_parent" > <TextView android_id="@+id/textView" android_layout_width="wrap_content" android_layout_height="wrap_content" android_layout_centerHorizontal="true" android_layout_centerVertical="true" android_text="" /> <ImageView android_id="@+id/imageView" android_layout_width="wrap_content" android_layout_height="wrap_content" android_layout_below="@+id/textView" android_layout_centerHorizontal="true" android_layout_marginTop="14dp" /> </RelativeLayout> Now, we are going to implement, step-by-step, the Activity class of the sample application. The code of the Activity class with the onCreate() method is as follows: public class Chapter9Activity extends Activity implementsCreateNdefMessageCallback{NfcAdapter mNfcAdapter;TextView mInfoText;ImageView imageView;@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.main);imageView = (ImageView) findViewById(R.id.imageView);mInfoText = (TextView) findViewById(R.id.textView);// Check for available NFC AdaptermNfcAdapter =NfcAdapter.getDefaultAdapter(getApplicationContext());if (mNfcAdapter == null){mInfoText = (TextView) findViewById(R.id.textView);mInfoText.setText("NFC is not available on this device.");finish();return;}// Register callback to set NDEF messagemNfcAdapter.setNdefPushMessageCallback(this, this);}@Overridepublic boolean onCreateOptionsMenu(Menu menu) {getMenuInflater().inflate(R.menu.main, menu);return true;}} As you can see in this code, we can check whether the device provides an NfcAdapter. If it does, we get an instance of NfcAdapter. Then, we call the setNdefPushMessageCallback() method to set the callback using the NfcAdapter instance. We send the Activity class as a callback parameter because the Activity class implements CreateNdefMessageCallback.In order to implement CreateNdefMessageCallback, we should override the createNdefMessage()method as shown in the following code block: @Overridepublic NdefMessage createNdefMessage(NfcEvent arg0) {Bitmap icon =BitmapFactory.decodeResource(this.getResources(),R.drawable.ic_launcher);ByteArrayOutputStream stream = new ByteArrayOutputStream();icon.compress(Bitmap.CompressFormat.PNG, 100, stream);byte[] byteArray = stream.toByteArray();NdefMessage msg = new NdefMessage(new NdefRecord[] {createMimeRecord("application/com.chapter9", byteArray), NdefRecord.createApplicationRecord("com.chapter9")});return msg;}public NdefRecord createMimeRecord(String mimeType, byte[]payload) {byte[] mimeBytes = mimeType.getBytes(Charset.forName("USASCII"));NdefRecord mimeRecord = newNdefRecord(NdefRecord.TNF_MIME_MEDIA,mimeBytes, new byte[0], payload);return mimeRecord;} As you can see in this code, we get a drawable, convert it to bitmap, and then to a byte array. Then we create an NdefMessage with two NdefRecords. The first record contains the mime type and the byte array. The first record is created by the createMimeRecord() method. The second record contains the Android Application Record ( AAR). The Android Application Record was introduced with Android Ice Cream Sandwich. This record contains the package name of the application and increases the certainty that your application will start when an NFC Tag is scanned. That is, the system firstly tries to match the intent filter and AAR together to start the activity. If they don't match, the activity that matches the AAR is started. When the activity is started by an Android Beam event, we need to handle the message that is sent by the Android Beam. We handle this message in the onResume() method of the Activity class as shown in the following code block: @Overridepublic void onResume() {super.onResume();// Check to see that the Activity started due to an AndroidBeamif (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(getIntent().getAction())) {processIntent(getIntent());}}@Overridepublic void onNewIntent(Intent intent) {// onResume gets called after this to handle the intentsetIntent(intent);}void processIntent(Intent intent) {Parcelable[] rawMsgs = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);// only one message sent during the beamNdefMessage msg = (NdefMessage) rawMsgs[0];// record 0 contains the MIME type, record 1 is the AARbyte[] bytes = msg.getRecords()[0].getPayload();Bitmap bmp = BitmapFactory.decodeByteArray(bytes, 0,bytes.length);imageView.setImageBitmap(bmp);} As you can see in this code, we firstly check whether the intent is ACTION_NDEF_DISCOVERED. This means the Activity class is started due to an Android Beam. If it is started due to an Android Beam, we process the intent with the processIntent() method. We firstly get NdefMessage from the intent. Then we get the first record and convert the byte array in the first record to bitmap using BitmapFactory . Remember that the second record is AAR, we do nothing with it. Finally, we set the bitmap of the ImageView component. The AndroidManifest.xml file of the application should be as follows: <manifest package="com.chapter9"android:versionCode="1"android:versionName="1.0" ><uses-permission android_name="android.permission.NFC"/><uses-feature android_name="android.hardware.nfc"android:required="false" /><uses-sdkandroid:minSdkVersion="14"android:targetSdkVersion="15" /><applicationandroid:icon="@drawable/ic_launcher"android:label="@string/app_name"android:theme="@style/AppTheme" ><activityandroid:name=".Chapter9Activity"android:label="@string/title_activity_chapter9" ><intent-filter><action android_name="android.intent.action.MAIN" /><categoryandroid:name="android.intent.category.LAUNCHER" /></intent-filter><intent-filter><actionandroid:name="android.nfc.action.NDEF_DISCOVERED" /><categoryandroid:name="android.intent.category.DEFAULT" /><data android_mimeType="application/com.chapter9" /></intent-filter></activity></application></manifest> As you can see in this code, we need to set the minimum SDK to API Level 14 or more in the AndroidManifest.xml file because these APIs are available in API Level 14 or more. Furthermore, we need to set the permissions to use NFC. We also set the uses feature in AndroidManifest.xml. The feature is set as not required. This means that our application would be available for devices that don't have NFC support. Finally, we create an intent filter for android.nfc.action.NDEF_DISCOVERED with mimeType of application/com.chapter9. When a device sends an image using our sample application, the screen will be as follows: Summary In this article, we firstly learned the Android Beam feature of Android. With this feature, devices can send data using the NFC hardware. We implemented a sample Android Beam application and learned how to use Android Beam APIs. Resources for Article : Further resources on this subject: Android 3.0 Application Development: Multimedia Management [Article] Animating Properties and Tweening Pages in Android 3-0 [Article] Android User Interface Development: Animating Widgets and Layouts [Article]
Read more
  • 0
  • 0
  • 4862

article-image-manifest-assurance-security-and-android-permissions-flash
Packt
29 Jun 2011
8 min read
Save for later

Manifest Assurance: Security and Android Permissions for Flash

Packt
29 Jun 2011
8 min read
Setting application permissions with the Android Manifest file When users choose to install an application on Android, they are always presented with a warning about which permissions the application will have within their particular system. From Internet access to full Geolocation, Camera, or External Storage permissions; the user is explicitly told what rights the application will have on their system. If it seems as though the application is asking for more permissions than necessary, the user will usually refuse the install and look for another application to perform the task they need. It is very important to only require the permissions your application truly needs, or else users might be suspicious of you and the applications you make available. How to do it... There are three ways in which we can modify the Android Manifest file to set application permissions for compiling our application with Adobe AIR. Using Flash Professional: Within an AIR for Android project, open the Properties panel and click the little wrench icon next to Player selection: The AIR for Android Settings dialog window will appear. You will be presented with a list of permissions to either enable or disable for your application. Check only the ones your application will need and click OK when finished. Using Flash Builder: When first setting up your AIR for Android project in Flash Builder, define everything required in the Project Location area, and click Next. You are now in the Mobile Settings area of the New Flex Mobile Project dialog. Click the Permissions tab, making sure that Google Android is the selected platform. You will be presented with a list of permissions to either enable or disable for your application. Check only the ones your application will need and continue along with your project setup: To modify any of these permissions after you've begun developing the application, simply open the AIR descriptor file and edit it as is detailed in the following sections. Using a simple text editor: Find the AIR Descriptor File in your project. It is normally named something like {MyProject}-app.xml as it resides at the project root. Browse the file for a node named <android> within this node will be another called <manifestAdditions> which holds a child node called <manifest>. This section of the document contains everything we need to set permissions for our Android application. All we need to do is either comment out or remove those particular permissions that our application does not require. For instance, this application needs Internet, External Storage, and Camera access. Every other permission node is commented out using the standard XML comment syntax of <!-- <comment here> -->: <uses-permission name="android.permission.INTERNET"/> <uses-permission name="android.permission.WRITE_EXTERNAL_ STORAGE"/> <!--<uses-permission name="android.permission.READ_PHONE_ STATE"/>--> <!--<uses-permission name="android.permission.ACCESS_FINE_ LOCATION"/>--> <!--<uses-permission name="android.permission.DISABLE_ KEYGUARD"/>--> <!--<uses-permission name="android.permission.WAKE_LOCK"/>-- > <uses-permission name="android.permission.CAMERA"/> <!--<uses-permission name="android.permission.RECORD_ AUDIO"/>--> <!--<uses-permission name="android.permission.ACCESS_ NETWORK_STATE"/>--> <!--<uses-permission name="android.permission.ACCESS_WIFI_ STATE"/>--> How it works... The permissions you define within the AIR descriptor file will be used to create an Android Manifest file to be packaged within the .apk produced by the tool used to compile the project. These permissions restrict and enable the application, once installed on a user's device, and also alert the user as to which activities and resources the application will be given access to prior to installation. It is very important to provide only the permissions necessary for an application to perform the expected tasks once installed upon a device. The following is a list of the possible permissions for the Android manifest document: ACCESS_COARSE_LOCATION: Allows the Geoloctaion class to access WIFI and triangulated cell tower location data. ACCESS_FINE_LOCATION: Allows the Geolocation class to make use of the device GPS sensor. ACCESS_NETWORK_STATE: Allows an application to access the network state through the NetworkInfo class. ACCESS_WIFI_STATE: Allows and application to access the WIFI state through the NetworkInfo class. CAMERA: Allows an application to access the device camera. INTERNET: Allows the application to access the Internet and perform data transfer requests. READ_PHONE_STATE: Allows the application to mute audio when a phone call is in effect. RECORD_AUDIO: Allows microphone access to the application to record or monitor audio data. WAKE_LOCK: Allows the application to prevent the device from going to sleep using the SystemIdleMode class. (Must be used alongside DISABLE_KEYGUARD.) DISABLE_KEYGUARD: Allows the application to prevent the device from going to sleep using the SystemIdleMode class. (Must be used alongside WAKE_LOCK.) WRITE_EXTERNAL_STORAGE: Allows the application to write to external memory. This memory is normally stored as a device SD card. Preventing the device screen from dimming The Android operating system will dim, and eventually turn off the device screen after a certain amount of time has passed. It does this to preserve battery life, as the display is the primary power drain on a device. For most applications, if a user is interacting with the interface, that interaction will prevent the screen from dimming. However, if your application does not involve user interaction for lengthy periods of time, yet the user is looking at or reading something upon the display, it would make sense to prevent the screen from dimming. How to do it... There are two settings in the AIR descriptor file that can be changed to ensure the screen does not dim. We will also modify properties of our application to complete this recipe: Find the AIR descriptor file in your project. It is normally named something like {MyProject}-app.xml as it resides at the project root. Browse the file for a node named <android> within this node will be another called <manifestAdditions>, which holds a child node called <manifest>. This section of the document contains everything we need to set permissions for our Android application. All we need to do is make sure the following two nodes are present within this section of the descriptor file. Note that enabling both of these permissions is required to allow application control over the system through the SystemIdleMode class. Uncomment them if necessary. <uses-permission android_name="android.permission.WAKE_LOCK" /> <uses-permission android_name="android.permission.DISABLE_ KEYGUARD" /> Within our application, we will import the following classes: import flash.desktop.NativeApplication; import flash.desktop.SystemIdleMode; import flash.display.Sprite; import flash.display.StageAlign; import flash.display.StageScaleMode; import flash.text.TextField; import flash.text.TextFormat; Declare a TextField and TextFormat pair to trace out messages to the user: private var traceField:TextField; private var traceFormat:TextFormat; Now, we will set the system idle mode for our application by assigning the SystemIdleMode.KEEP_AWAKE constant to the NativeApplication.nativeApplication.systemIdleMode property: protected function setIdleMode():void { NativeApplication.nativeApplication.systemIdleMode = SystemIdleMode.KEEP_AWAKE; } We will, at this point, continue to set up our TextField, apply a TextFormat, and add it to the DisplayList. Here, we create a method to perform all of these actions for us: protected function setupTraceField():void { traceFormat = new TextFormat(); traceFormat.bold = true; traceFormat.font = "_sans"; traceFormat.size = 24; traceFormat.align = "left"; traceFormat.color = 0xCCCCCC; traceField = new TextField(); traceField.defaultTextFormat = traceFormat; traceField.selectable = false; traceField.multiline = true; traceField.wordWrap = true; traceField.mouseEnabled = false; traceField.x = 20; traceField.y = 20 traceField.width = stage.stageWidth-40; traceField.height = stage.stageHeight - traceField.y; addChild(traceField); } Here, we simply output the currently assigned system idle mode String to our TextField, letting the user know that the device will not be going to sleep: protected function checkIdleMode():void { traceField.text = "System Idle Mode: " + NativeApplication. nativeApplication.systemIdleMode; } When the application is run on a device, the System Idle Mode will be set and the results traced out to our display. The user can leave the device unattended for as long as necessary and the screen will not dim or lock. In the following example, this application was allowed to run for five minutes without user intervention: How it works... There are two things that must be done in order to get this to work correctly and both are absolutely necessary. First, we have to be sure the application has correct permissions through the Android Manifest file. Allowing the application permissions for WAKE_LOCK and DISABLE_KEYGUARD within the AIR descriptor file will do this for us. The second part involves setting the NativeApplication.systemIdleMode property to keepAwake. This is best accomplished through use of the SystemIdleMode.KEEP_AWAKE constant. Ensuring that these conditions are met will enable the application to keep the device display lit and prevent Android from locking the device after it has been idle.
Read more
  • 0
  • 0
  • 4806
Modal Close icon
Modal Close icon