Quantcast
Channel: Envato Tuts+ Code - Mobile Development
Viewing all 1836 articles
Browse latest View live

Android SDK: Next Steps

$
0
0

In this series, we’ve begun learning how to develop Android applications from scratch. We started exploring the development tools, got acquainted with the basic elements in an application project, looked at user interface design, interactivity, resources, and data, and we’ve also took a closer look at what happens when your application is running. What we’ve covered so far should put you in a good position to get started creating functional Android applications, but Android has a lot more to offer so the range of possibilities is virtually endless. You may therefore struggle to choose what to learn next. In this part, we’ll wrap up the series by pointing out some possible directions for future learning. After this, the final part will be a quiz on what we covered throughout the series.


Introduction

There are lots of possible directions you can take for building on the Android foundation you have gained by reading this series. Of course, if you have particular projects planned, then these will dictate some of what you will learn next. However, there is a lot to the Android platform, with many application elements common to most of the projects you will work on. In this tutorial, we’ll zoom in on some of the most useful topics to look at to start building your Android skill set.


1. Data

Step 1

You can use the simple application project we created earlier in this series to try out the new Android skills you will learn. Remember that we tried saving data to the shared preferences. You could improve that example by saving data to a file. Try letting the user submit and save data by leveraging an EditText view and a button. Write the user’s data to a file, read it back in when the application launches, and display it in a TextView view. This way you can save persistent data which will appear next time the application is run.

Step 2

Another essential skill is retrieving data from a remote resource, such as a web service. To accomplish this, add an inner AsyncTask class to your Activity class in which you fetch the remote data. When the data is retrieved, display it in your application. Additionally, you may want to parse or format the data if the data your application receives is XML, JSON, or another common format. See Connecting to the Network for sample code you can use as a starting point.

Step 3

The other main data storage option you are likely to find useful in many apps is using a SQLite database. Try this out by creating a SQLiteOpenHelper class, in which you define the architecture of the database, such as tables and columns. Elsewhere in the application, you can then tell the SQLiteOpenHelper to write data to the database and to read from it using a cursor, presenting the results in your application’s user interface. Again, you may want to try letting the user enter data to save in the database and present the results on future runs of the application. In addition to inserting records and querying the database, try updating and deleting records as wel. See Saving Data in SQLite Databases for more information and sample code to get you started.


2. App Screens

Step 1

In the application we created, we used a single screen in the user interface screen. Try adding to this by creating a second activity class in your app using the File > New > Class menu option. Add a button to the first screen, the main activity, which launches the second activity when the user taps it. For example, if the application would be a game, the button could read “How to Play” and the second activity could be named How.java. Create a layout file for the second activity, including a TextView with text stored in the res/values strings XML file. If the application would be a game, the second activity could contain information about how to play the game. Many of the information sections in your applications will use this simple pattern.

In the onClick handler in the first activity, you can launch the “How to Play” activity using intents. Visit Starting Another Activity for more information about this. Once you have a second activity in your application, try passing data to it from the first activity using the putExtra method. You can also try starting an activity for a result, letting the second activity do something, and then return data to the first one. You can retrieve the result data in the onActivityResult method of the first activity. Take a look at the Activity class reference for an example of this.

Step 2

As a next step, you could try to include some of the different user interface views in your activities. You will notice that different types of views require different approaches to implement them. Once you’ve got a good grasp of using different view types, try using fragments so you can start reusing parts of the user interface in various places of your application.

Another user interface component you’ll find useful is the list View. With a list View, the screen presents a list of items. The list view is populated from a data source using an adapter, which maps data to views. You can use a ListActivity instead of a standard Activity class for this. In a list activity, you can override set methods for responding to user interaction with the items in a list, which makes the list a useful component for many application types. Visit List View for a functional example implementing a list view.

Applications with a look and feel that is consistent with the Android system itself tend to perform better. Whenever possible, you should try to use standard Android user interface elements rather than creating your own custom components. For this reason, you may want to try getting acquainted with the Action Bar and keep in mind whenever you design the user interface and navigation model of your applications.


3. Multimedia

You can create Android applications using various types of media, such as audio and video, animation and image capturing through the device’s camera, including video capture. The Android system provides standard methods you can use to access resources, such as the camera, with actions for specific tasks including video recording. Browse the Multimedia guide of the Developer Guide for more information.

As we saw earlier in this series, you can build visual elements within your Android applications using XML to create shape drawables. You can also use XML to define animations with code controlling how the animations elapse. Animations on Android let you add dynamic effects to your user interface,with a variety of supported effects, such as fading, rotating, flipping, and various other transition types (Adding Animations).


4. Interacting with Other Applications

Step 1

One of the benefits of developing on Android is that you can make use of existing resources of the platform, including other applications. As I mentioned earlier in this series, you can share data with other applications and make use of that shared data in your own applications. You can also let users share content from your applications using email, messages, and social networks. The simplest and most reliable way of doing this is via the send intent. When your applications launches a send action, the operating system will present a list of the applications the user can send content to. Be sure to read up on this topic in the Sending Simple Data to Other Apps guide, which also includes examples.

Step 2

The send action is one example of launching facilities on Android from your own applications, but there are lots of ways in which you can accomplish this so make sure to try some of them in your own projects. For example, you can use the dial action to dial a number, and the view action to view web pages in the browser, or locations in the Maps application. You can also retrieve data from the device’s built-in sensors, letting your application capture and process location and environmental data. In many cases, you can trigger these actions in ways that return information back to your application when the launched action is finished, creating a dialog between your application and the Android context. This way, your application fully exploit the mobile nature of the Android device.


5. Resources

Step 1

We’ve touched on several potential topics for future learning, but in reality we have barely scratched the surface of what’s possible on the Android platform. The platform is constantly changing and the list of what is possible is growing ever longer. The recommended techniques for common tasks change regularly as well so it is vital to keep learning if you want to continue developing high quality Android applications.

Here are some useful resources to bookmark:

  • Visit the Android Developers Blog for new and upcoming platform features. The blog often includes functional code examples that you can learn from.
  • The Vogella Android Tutorials are one of the most valuable Android learning resources on the web. The Vogella website often includes complete examples of techniques only covered in excerpts on the official Developer Guide.
  • The Android Developers on Google+ is a good place to read up on announcements and discussions on Android development.

As with any development platform, you will find yourself with plenty of questions when you learn Android, most of which will lead you to a Google search. As you’ll learn, many common questions have been answered comprehensively on Stack Overflow so you will soon become accustomed to visiting Stack Overflow if you aren’t already.


Conclusion

In this series of tutorials, my goal has been to teach you the basics of Android development. If you’ve learned any programming or development skill in the past, you know that the learning process does not end here. If you plan to continue developing for the Android platform, you’ll be able to build on what we’ve learned in this series, adding to your Android toolbox as you go. To finish this series up, the next installment will be a quiz testing you on what you’ve learned so far. Be prepared!


Create a Balance Ping-Pong Game

$
0
0

In this tutorial, I’ll be showing you how to create a balance game in Corona SDK. You’ll learn more about touch controls and collision detection without physics. The objective of the game is to keep the ball from touching the floor. Read on.


1. Application Overview

App Overview

Using ready-made graphics, we’ll create an entertaining game using Lua and the Corona SDK APIs. The player will be able to move a ping-pong paddle on the screen in order to hit a ball. You can modify the parameters in the code to customize the game.


2. Target Device

Target Device

The first thing we need to do is select the platform we want to run our application on so we’re able to choose the size of the images we’ll use.

The iOS platform has the following requirements:

  • iPad 1/2/Mini: 1024px x 768px, 132 ppi
  • iPad Retina: 2048px x 1536px, 264 ppi
  • iPhone/iPod Touch: 320px x 480px, 163 ppi
  • iPhone/iPod Retina: 960px x 640px, 326 ppi
  • iPhone 5/iPod Touch: 1136px x640px, 326 ppi

Because Android is an open platform, there are many different devices and resolutions. A few of the more common screen characteristics are:

  • Asus Nexus 7 Tablet: 800px x 1280px, 216 ppi
  • Motorola Droid X: 854px x 480px, 228 ppi
  • Samsung Galaxy SIII: 720px x 1280px, 306 ppi

In this tutorial, we’ll be focusing on the iOS platform in terms of graphics. In particular, we’ll be developing for the iPhone and iPod touch. However, the code of this tutorial can also be used if you target the Android platform.


3. Interface

Interface

We’ll use a simple user interface involving multiple shapes, buttons, bitmaps, and more. The graphics that we’ll use for this tutorial can be found in the project included with this tutorial.


4. Export Graphics

Export Graphics

Depending on the device you’ve selected, you may need to convert the graphics to the recommended resolution (ppi), which you can do in your favorite image editor. I used the Adjust Size… option in the Tools menu in the Preview application on OS X. Remember to give the images a descriptive name and save them in your project folder.


5. Application Configuration

We’ll use a configuration file, config.lua, to make the application go full screen across devices. The configuration file shows the original screen size and the method used to scale the content in case the application is run on another resolution.

application =
{
    content =
    {
        width = 320,
        height = 480,
        scale = "letterbox"
    },
}

6. Main.lua

Let’s write the actual application. Open your preferred Lua editor. Any plain text editor will work, but it is recommended to use a text editor that has syntax highlighting. Create a new file and save it as main.lua in your project folder.


7. Project Structure

We’ll structure our code as if it were a class. If you’re familiar with ActionScript or Java, you should find the project structure familiar.

Necesary Classes
Variables and Constants
Declare Functions
    contructor (Main function)
    class methods (other functions)
call Main function

8. Hide Status Bar

display.setStatusBar(display.HiddenStatusBar)

This code snippet hides the status bar. The status bar is the bar at the top of the device’s screen that shows the time, signal, and other indicators.


9. Background

Background

A simple background for the application’s user interface. The code snippet below, draws the background to the screen.

-- Graphics
-- [Background]
local bg = display.newImage('bg.png')

10. Title View

Title View

This is the title view. It’s the first interactive screen to appear in our game. These variables store its components.

-- [Title View]
local title
local playBtn
local creditsBtn
local titleView

11. Credits View

Credits View

The credits view shows the credits and copyright of the application. This variable is used to store it.

-- [CreditsView]
local creditsView

12. Instructions Message

Instructions

An message with instructions will appear at the start of the game and it will disappear after the first tap.

-- Instructions
local ins

13. Paddle

Paddle

This is the graphic for the ping-pong paddle. It will be placed at the view’s center.

-- Paddle
local paddle
local paddleTop
local paddleBottom

14. Ball

Ball

And this is the graphic for the ping-pong ball used in the game.

-- Ball
local ball

15. Alert

Alert

The alert is displayed when the player misses the ball and the game is over. It displays a message and ends the game.

-- Alert
local alertView

16. Sounds

Sounds

We’ll use sound effects to spice up the game. The sounds used in this game can be found on freesound, a collaborative database of Creative Commons Licensed sounds.

-- Sounds
local pong = audio.loadSound('pong.mp3')

17. Variables

The following code snippet shows the variables that we’ll use. Read the comments to understand what each variable is used for.

-- Variables
local scoreTF -- score textfield
local scale = 1.1 -- initial ball scale
local variation = 0.05 -- controls the scale variation
local ballX = 0
local ballY = 0
local ballVar = 0.5 -- ball variation

18. Declare Functions

Declare all functions as local at the start.

-- Functions
local Main = {}
local startButtonListeners = {}
local showCredits = {}
local hideCredits = {}
local showGameView = {}
local gameListeners = {}
local startGame = {}
local hitTestObjects = {}
local update = {}
local movePaddle = {}
local alert = {}

19. Constructor

Next, we create the function that will initialize the game logic.

function Main()
  -- code...
end

20. Add Title View

We start by placing the title view in the stage and call a function that will add tap listeners to the buttons.

function Main()
  titleBg = display.newImage('titleBg.png', 26, 72)
  playBtn = display.newImage('playBtn.png', 125, 225)
  creditsBtn = display.newImage('creditsBtn.png', 115, 290)
  titleView = display.newGroup(titleBg, playBtn, creditsBtn)
  startButtonListeners('add')
end

21. Start Button Listeners

The following function adds the necessary listeners to the TitleView‘s buttons.

function startButtonListeners(action)
  if(action == 'add') then
    playBtn:addEventListener('tap', showGameView)
    creditsBtn:addEventListener('tap', showCredits)
  else
    playBtn:removeEventListener('tap', showGameView)
    creditsBtn:removeEventListener('tap', showCredits)
  end
end

22. Show Credits

The credits screen is shown when the user taps the about button. A tap listener is added to the credits view to dismiss it when the user taps it.

function showCredits:tap(e)
  playBtn.isVisible = false
  creditsBtn.isVisible = false
  creditsView = display.newImage('credits.png', 0, display.contentHeight)
  lastY = titleBg.y
  transition.to(titleBg, {time = 300, y = (display.contentHeight * 0.5) - (titleBg.height + 50)})
  transition.to(creditsView, {time = 300, y = (display.contentHeight * 0.5) + 35, onComplete = function() creditsView:addEventListener('tap', hideCredits) end})
end

23. Hide Credits

When the user taps credits view, it is animated out of the stage and removed.

function hideCredits:tap(e)
  transition.to(creditsView, {time = 300, y = display.contentHeight + 25, onComplete = function() creditsBtn.isVisible = true playBtn.isVisible = true creditsView:removeEventListener('tap', hideCredits) display.remove(creditsView) creditsView = nil end})
  transition.to(titleBg, {time = 300, y = lastY});
end

24. Show Game View

When the play button is tapped, the title view is animated off the screen and the game view is revealed. There are a number of moving parts so we’ll take a closer look at each of them.

function showGameView:tap(e)
  transition.to(titleView, {time = 300, x = -titleView.height, onComplete = function() startButtonListeners('rmv') display.remove(titleView) titleView = nil bg:addEventListener('tap', startGame) end})

25. Instructions Message

The following code snippet adds the instruction message.

ins = display.newImage('ins.png', 112, 370)

26. Paddle Parts

Next, we add the paddle parts. It is split up into two parts for better collision detection.

-- Paddle
  paddleBottom = display.newImage('paddleBottom.png', 138.6, 262)
  paddleTop = display.newImage('paddleTop.png', 110, 166)
  paddle = display.newGroup(paddleBottom, paddleTop)

27. Ball

We add the ball and set its scale.

-- Ball
  ball = display.newImage('ball.png', 146, 201)
  ball:scale(scale, scale)

28. Score

We create a score text field at the top right of the stage.

-- Score
  score = display.newImage('score.png', 260, 0)
  scoreTF = display.newText('0', 278, 21, 'Marker Felt', 30)
  scoreTF:setTextColor(238, 238, 238)
  gameListeners('add')
end

29. Game Listeners

The following function adds the necessary listeners for starting the game logic.

function gameListeners(action)
  if(action == 'add') then
    bg:addEventListener('touch', movePaddle)
  else
    bg:removeEventListener('touch', movePaddle)
    Runtime:removeEventListener('enterFrame', update)
  end
end

30. Start Function

The startGame function removes the instruction message and adds a listener to the main function of the game. In the function, a random y position is selected from the previously created table and subsequently adds physics to the newly created object. We add a collision listener to every enemy and also add them to the enemies table.

function startGame()
  display.remove(ins)
  bg:removeEventListener('tap', startGame)
  Runtime:addEventListener('enterFrame', update)
end

31. Hit Test Objects

For collision detection without using physics, we use a great function, which you can find on the Corona Labs Code Exchange website.

function hitTestObjects(obj1, obj2)
        local left = obj1.contentBounds.xMin <= obj2.contentBounds.xMin and obj1.contentBounds.xMax >= obj2.contentBounds.xMin
        local right = obj1.contentBounds.xMin >= obj2.contentBounds.xMin and obj1.contentBounds.xMin <= obj2.contentBounds.xMax
        local up = obj1.contentBounds.yMin <= obj2.contentBounds.yMin and obj1.contentBounds.yMax >= obj2.contentBounds.yMin
        local down = obj1.contentBounds.yMin >= obj2.contentBounds.yMin and obj1.contentBounds.yMin <= obj2.contentBounds.yMax
        return (left or right) and (up or down)
end

32. Scale Ball

The update function, shown below, runs every frame. In this function, we first scale the ball based on the values set by the variables.

function update()
  -- Scale Balls
  scale = scale - variation
  ball.xScale = scale
  ball.yScale = scale

33. Ball Raise

This part increases the ball size to simulate an increase in its height.

-- Raising
  if(math.floor(ball.xScale * 10) >= 15) then
    variation = 0.05
  end

34. Ball Missed

The same method is used to check if the ball has touched the floor, an essential aspect of the game.

-- Missed
  if(math.floor(ball.xScale * 10) < 3) then
    alert()
  end

35. Move Ball

In the following code snippet, we move the ball. Based on the value of the variables, it is moved up or down.

-- Move Ball
  ball.x = ball.x - ballX
  ball.y = ball.y - ballY

36. Ball Hit

A scale is set to be the same paddle height, which means that the ball has touched the paddle. We then increase the score and play a sound to provide feedback to the user.

-- Falling and Hit with paddle
  if(math.floor(ball.xScale * 10) == 3 and hitTestObjects(paddleTop, ball)) then
    variation = -0.05
    -- Increase Score
    scoreTF.text = tostring(tonumber(scoreTF.text) + 1)
    -- Play Sound
    audio.play(pong)

37. Change Ball Direction

The paddle is divided in four sections, top left, top right, bottom left, and bottom right. Each section moves the ball in a different direction.

-- Move Ball based on where it hits
    if(ball.x < paddle.x + 50) then       ballX = (math.random() * 0.5) + ballVar     end     if(ball.x  > paddle.x) then
      ballX = (math.random() * -0.5) - ballVar
    end
    if(ball.y < paddle.y + 75) then       ballY = (math.random() * 0.5) + ballVar     end     if(ball.y > paddle.y - 70) then
      ballY = (math.random() * -0.5) - ballVar
    end
    -- Increase moving distance
    ballVar = ballVar + 0.025 -- Every four hits increases 0.1
  end
end

38. Move Paddle

The movePaddle function handles the movement of the paddle using touch controls.

function movePaddle(e)
  if(e.phase == 'moved') then
    paddle.x = e.x
    paddle.y = e.y
  end
end

39. Alert

The alert function creates an alert view. The function animates the alert view onto the screen and ends the game.

function alert()
  gameListeners('rmv')
  alert = display.newImage('alert.png', (display.contentWidth * 0.5) - 105, (display.contentHeight * 0.5) - 55)
  transition.from(alert, {time = 300, xScale = 0.5, yScale = 0.5})
end

40. Call Main Function

In order to start the game, the Main function needs to be invoked. With the rest of the code in place, we do that here.

Main()

41. Loading Screen

Loading Screen

On the iOS platform, the file named Default.png is displayed while the application is launching. Add this image to your project’s source folder, it will be automatically added by the Corona compiler.


42. Icon

Icon

Using the graphics you created earlier, you can now create a nice icon. The dimensions of the icon size for a non-retina iPhone are 57px x 57px, while the retina version needs to be 114px x 114px. The artwork for iTunes is required to be 1024px x 1024px. I suggest creating the iTunes artwork first and then creating the smaller sized images by scaling the iTunes artwork down to the correct dimensions. There is no need to make the application icon glossy or add rounded corners as this is taken care of by the operating system for you.


43. Testing in Simulator

Testing

It’s time to test our application in the simulator. Open the Corona Simulator, browse to your project folder, and click Open. If everything works as expected, you’re ready for the final step.


44. Build Project

Build

In the Corona Simulator, go to File > Build and select the target device. Fill out the required fields and click Build. Wait a few seconds and your application is ready to test on a device and/or to be submitted for distribution.


Conclusion

In this tutorial, we’ve learned about touch listeners, and collision detection. Experiment with the final result and try to modify the game to create your own version fo the game. I hope you liked this tutorial and found it helpful. Thank you for reading.

Android SDK: Quiz

$
0
0

In the Android from Scratch series, we learned the basic concepts of Android that you need to know about in order to start creating applications for the platform. Along the way, we covered various aspects of Android development, including Java development, using XML, user interface design, project structure, data storage, and the publication process. Find out how much you’ve managed to retain about what we covered in the series by taking a quiz.

iOS 2013: A Year in Review and 2014 Predictions

$
0
0

For iOS developers, 2013 was a pivotal year. I’d even go as far as saying that it was the most significant year since the introduction of the iPhone, almost seven years ago. The reason is of course the unveiling of iOS 7. Let’s take a look at some of the key moments of 2013 and take a sneak peak at what 2014 has in store for us.


iOS 7

The release of iOS 7 was without a doubt this year’s key event for iOS developers. For consumers, the UI and UX changes are the most important changes Apple introduced in iOS 7, but they’re only the tip of the proverbial iceberg for iOS developers. It’s true that the visual redesign of iOS is the most striking feature of iOS 7, but the operating system has undergone a major redesign both visually and under the hood.

The introduction of iOS 7.

User Interface

Even though the visual redesign of iOS 7 isn’t revolutionary, it is more than an incremental update of the platform. In fact, in some cases you can hardly speak of changes as some user interface concepts consumers have come accustomed to have been rebuilt from scratch, such as the Application Switcher, Spotlight, Notification Center, Control Center, and all of Apple’s own iOS applications.

It seems, though, as if some of the changes were a bit too radical. Since the unveiling of iOS 7 during WWDC, Apple’s annual developer’s conference, Apple has reverted some of the more radical changes introduced in iOS 7, such as the Springboard animations and the ability to disable the system-wide parallax effect. The ultra-thin fonts shown during the WWDC 13 keynote didn’t even make it in the final release of iOS 7 in September 2013.

The redesigned user interface of iOS 7.

It seems that most people agree that iOS 7 wasn’t a finished product like iOS 5 or 6 were, which isn’t surprising considering the scale of the redesign. The operating system has undergone so many changes that it would’ve been a miracle if iOS 7 was as polished as iOS 6 was last year.

In addition to the visual overhaul of iOS, the average user should also be excited about the addition of Control Center and the improvements made to Notification Center. Another great feature is iCloud Keychain, although, it isn’t perfect yet and will need to be improved to be really useful. Third party solutions, such as 1Password and LastPass, are more polished and more advanced in terms of feature set.

Under The Hood

As with every major release of iOS, numerous new APIs were introduced, but it is no surprise that the visual redesign received the most attention for obvious reasons. At first, both developers and technology pundits had mixed feelings about the redesign of iOS. However, several months later, there’s a general consensus that iOS 7 is a clear step forward. The question at this point is whether it is a large enough step forward to keep up with Android.

I’m very excited about iOS 7 as it introduces several new APIs and expands numerous existing APIs. The most prominent additions introduced in iOS 7 are TextKit, which iOS 7 heavily relies upon, UIKit Dynamics and Motion Effects, NSURLSession to replace NSURLConnection, improvements of the Multitasking APIs, JavaScript Core, and AirDrop.

Games

The iOS platform continues to be an amazing platform for game development. This will only continue with the introduction of SpriteKit, the Game Controller framework, and several improvements to Game Center. It is also worth noting that iOS 7 supports OpenGL ES 3.0 and provides improved support for OpenGL ES 2.0.

Automatic Updates

In addition to these new and improved APIs, developers should be excited about another great feature introduced in iOS 7, automatic updates. It may not be ideal for power users, like most developers, but I can tell you that it’s a blessing for the average user like many of your family and friends. For developers, it is something to be excited about as it means that your customer base will migrate much faster to new versions of your applications.


Xcode 5

Even though Xcode 5 isn’t strictly tied to iOS 7, its introduction at WWDC 2013 was an important milestone for Cocoa developers. The user interface of Apple’s integrated development environment (IDE) has received a redesign and a number of new features were introduced, such as Automatic Configuration, much better support for Auto Layout, better integration with source control, added support for testing and continuous integration, and the Asset Catalog.

The introduction of Xcode 5 is something to be excited about if you're a developer.

As with every release of Xcode, version 5 received its share of criticism due to stability and compatibility issues, but it is without a doubt an important step forward for both Apple and the Cocoa developer community. I love using Xcode 5 and only – reluctantly – fire up Xcode 4 if there’s no other option. Xcode 5 continues to be one of the best IDEs available today and is an indispensable tool for Cocoa development.


iOS Product Line

iPhone 5S

As with every S release of the iPhone product line, the iPhone 5S was an iterative release with most of the changes under the hood. The most significant change was the unveiling of the A7 processor and the M7 motion co-processor. The A7 is a chip with an incredible performance yet still being power-efficient. The most notable feature, however, which came as a big surprise, is that it’s the first 64-bit mobile chip. This means that applications can run and be written in 64-bit. One of the advantages of a 64-bit mobile chip is a better performance per watt, which will be especially noticeable for games and computing intensive applications. However, most applications won’t really benefit just yet from the 64-bit architecture of the A7 processor.

The M7 motion co-processor is a nice addition to the iPhone 5S – and the new iPad models. The M7′s primary task is to collect data from the device’s sensors, the accelerometer, gyroscope, and compasses. Another interesting aspect of the M7 is that it does its job even when the device is asleep. This opens up a lot of possibilities for third party applications to integrate with the M7 through Apple’s Core Motion framework. The net result for consumers is better battery life and applications with more as well as more accurate motion data (e.g., fitness applications, location services, etc.).

The most important changes of the iPhone 5S are under the hood.

The most prominent feature for the general public was the addition of a fingerprint sensor integrated into the device’s home button. Based on the reactions in the technology community, it works better than what most people had expected. It isn’t flawless, but, when set up correctly, it works amazingly well. At the moment, the fingerprint sensor has no public API and can therefore not be accessed by third party applications, but I can imagine – and hope – that Apple will open this up in the future so that developers can benefit from this extra level of security in their own applications.

Alongside the iPhone 5S, Apple introduced the iPhone 5C. People were lukewarm about its introduction as it’s basically an iPhone 5 with a plastic shell instead of the aluminum housing of the 5S. For developers, its introduction isn’t that significant.

iPad Air and iPad Mini

The iPad received a minor update and is now called iPad Air to reflect its thin and lightweight design. The more notable update was that of the iPad Mini, which now sports a retina display. Like the iPhone 5S, the iPad Air and the iPad Mini come with the new 64-bit A7 processor and the M7 motion co-processor. Most of us were a bit surprised and disappointed that the updated iPads lack the new fingerprint sensor found in the iPhone 5S.

The changes of the iPad line-up were incremental.

Most iOS developers were secretly hoping that Apple would stop producing non-retina iOS devices, that is, the iPad 2 and the non-retina iPad Mini. Unfortunately, Apple announced it will continue to sell the original iPad Mini as well as the iPad 2, which was introduced more than two and a half years ago. It looks like iOS developers will need to support non-retina devices for quite some time.


Competition

In 2007, Apple had an almost insurmountable head start and the introduction of Android in November 2007 didn’t change that. In recent years, however, Android has not only become the dominant player in the mobile space, the operating system has matured so fast and consistently that it is without a doubt superior to iOS in several aspects. Google improves Android at a rapid pace and the integration with its popular web services, such as GMail, Maps, and Search, is one of the key factors of its success.

Anroid KitKat is another step forward for Google and the Android platform.

It seems that Windows Phone isn’t really taking of or gaining a significant share of the mobile market. This saddens me a little as it would be beneficial for the mobile space if a third major competitor would be part of the game. The exit of CEO Steve Ballmer marked an important milestone in Microsoft’s history and it’ll be interesting to see how this affects Microsoft in the future and who will be at the helm in the coming years.


No Watch, No Apple TV SDK

At one point, the hype of an Apple smart watch reached a level at which many people believed Apple was about to announce a smart watch. Well. That didn’t happen. The Apple TV didn’t get a significant update either and it remains a mystery why Apple hasn’t opened the Apple TV up to third party developers. I hope this will change in 2014.


2014

For Apple, 2014 will be as important as 2013 was. It is clear that iOS 7 still has rough edges, even after the updates of the past few months since its release. Developers and companies are gradually updating their applications to iOS 7 and finding ways to cope with the UI and UX changes.

The rate with which users upgrade from one major iOS release to another has always been incredible, especially when compared with other platforms, such as Android. This is one of the most important advantages that iOS developers have over other mobile platforms. The same is true for OS X and Apple is well aware of this advantage. It is no coincidence that OS X Mavericks has been a free upgrade for every OS X user with compatible hardware. The result is that iOS applications are much faster at adopting new iOS features and developers are eager to require the latest iOS version. This will not change in 2014 and that is a good thing.

The release of iOS 8 will be another milestone for Apple and even more so for iOS developers. Developers have done their best to deal with the changes that iOS 7 introduced, but there are still many, many problems with iOS 7 especially from a developer’s perspective. Apple has been addressing a lot of them in recent updates, but the real test for Apple will be iOS 8. It will give Apple a second chance at iOS 7 so to speak. I love iOS 7 the more I use it, but there are a number of problems that need solving.

It is notoriously difficult to predict what Apple has in store for us, but I hope the Apple TV will finally be open for third party applications. I am not terribly excited about a smart watch, but it is more than likely that we’ll see something in the wearables space from Apple in 2014. What do you think or hope Apple will introduce in 2014? Share it in the comments or tell me on Twitter.

Networking with NSURLSession: Part 1

$
0
0

From a developer’s perspective, one of the more significant changes in iOS 7, and OS X Mavericks for that matter, is the introduction of NSURLSession. Even though NSURLSession may seem daunting at first glance, it’s important that you understand what it is, how it relates to NSURLConnection, and what the differences are. In this series, I will take you through the fundamentals of NSURLSession so you can take advantage of this new technology in your own applications.


Why Replace NSURLConnection?

The first question you may be asking yourself is why Apple found it necessary to introduce NSURLSession while we are perfectly happy with NSURLConnection. The real question is whether you are happy with NSURLConnection. Do you remember that time you were cursing and throwing things at NSURLConnection? Most Cocoa developers have been in that place, which is why Apple decided to go back to the drawing board and create a more elegant solution, better suited for the modern web.

Even though NSURLSession and NSURLConnection have a lot in common in terms of how they work, at a fundamental level, they are quite different. Apple created NSURLSession to resemble the general concepts of NSURLConnection, but you will learn in the course of this series that NSURLSession is modern, easier to use, and built with mobile in mind.


What is NSURLSession?

Before I discuss the differences between NSURLSession and NSURLConnection, it’s a good idea to first take a closer look at what NSURLSession is. Despite its name, NSURLSession isn’t just another class you can use in an iOS or OS X application. NSURLSession is first and foremost a technology just like NSURLConnection is.

Sessions are Containers

NSURLSession and NSURLConnection both provide an API for interacting with various protocols, such as HTTP and HTTPS. The session object, an instance of the NSURLSession class, is what manages this interaction. It is a highly configurable container with an elegant API that allows for fine-grained control. It offers features that are absent in NSURLConnection. What’s more, with NSURLSession, you can accomplish tasks that are simply not possible with NSURLConnection, such as implementing private browsing.

Tasks

The basic unit of work when working with NSURLSession is the task, an instance of NSURLSessionTask. There are three types of tasks, data tasks, upload tasks, and download tasks.

  • You’ll most often use data tasks, which are instances of NSURLSessionDataTask. Data tasks are used for requesting data from a server, such as JSON data. The principal difference with upload and download tasks is that they return data directly to your application instead of going through the file system. The data is only stored in memory.
  • As the name implies, upload tasks are used to upload data to a remote destination. The NSURLSessionUploadTask is a subclass of NSURLSessionDataTask and behaves in a similar fashion. One of the key differences with a regular data task is that upload tasks can be used in a session created with a background session configuration.
  • Download tasks, instances of NSURLSessionDownloadTask, inherit directly from NSURLSessionDataTask. The most significant difference with data tasks is that a download task writes its response directly to a temporary file. This is quite different from a regular data task that stores the response in memory. It is possible to cancel a download task and resume it at a later point.

As you can imagine, asynchronicity is a key concept in NSURLSession. The NSURLSession API returns data by invoking a completion handler or through the session’s delegate. The API of NSURLSession was designed with flexibility in mind as you’ll notice a bit later in this tutorial.

Meet the Family

As I mentioned earlier, NSURLSession is both a technology and a class that you’ll be working with. The NSURLSession API houses a number of classes, but NSURLSession is the key component sending requests and receiving responses. The configuration of the session object, however, is handled by an instance of the NSURLSessionConfiguration class. The NSURLSessionTask class and its three concrete subclasses are the workers and are always used in conjunction with a session as it is the session that creates the task objects.

Delegation

Both NSURLSession and NSURLConnection rely heavily on the delegation pattern. The NSURLSessionDelegate protocol declares a handful of delegate methods for handling events at the session-level. In addition, the NSURLSessionTask class and subclasses each declare a delegate protocol for handling task-level events.

Old Friends

The NSURLSession API builds on top of classes that you’re already familiar with, such as NSURL, NSURLRequest, and NSURLResponse.


What are the differences?

How does NSURLSession differ from NSURLConnection? This is an important question, because NSURLConnection is not being deprecated by Apple. You can still use NSURLConnection in your projects. Why should you use NSURLSession?

The first thing to understand is that the NSURLSession instance is the object that manages the request and response. This is similar to how NSURLConnection works, but the key difference is that the configuration of the request is handled by the session object, which is a long lived object. This is done through the NSURLSessionConfiguration class. Not only does it provide the NSURLSession API fine-grained configuration through the NSURLSessionConfiguration class, it encourages the separation of data (request body) from metadata. The NSURLSessionDownloadTask illustrates this well by directly writing the response to the file system.

Authentication is easier and handled more elegantly by NSURLSession. The NSURLSession API handles authentication on a connection basis instead of on a request basis, like NSURLConnection does. The NSURLSession API also makes it more convenient to provide HTTP options and each session can have a separate storage container depending on how you configure the session.

In the introduction, I told you that NSURLSession provides a modern interface, which integrates gracefully with iOS 7. One example of this integration is NSURLSession‘s out-of-process uploads and downloads. NSURLSession is optimized to preserve battery life, supports pausing, canceling, and resuming of tasks as well as UIKit’s multitasking API. What is not to love about NSURLSession?


Getting Your Feet Wet

Step 1: Project Setup

A new API is best learned by practice so it’s time to fire up Xcode and get our feet wet. Launch Xcode 5, create a new project by selecting New > Project… from the File menu, and select the Single View Application template from the list of iOS application templates.

Create a new project in Xcode 5.

Give your project a name, tell Xcode where you’d like to save it, and hit Create. There’s no need to put the project under source control.

Configure the project.

Step 2: Create a Session Object

When working with NSURLSession, it is important to understand that the session object, an instance of NSURLSession, is the star player. It handles the requests and responses, configures the requests, manages session storage and state, etc. Creating a session can be done several ways. The quickest way to get started is to use NSURLSession‘s sharedSession class method as shown below.

- (void)viewDidLoad {
    [super viewDidLoad];
    NSURLSession *session = [NSURLSession sharedSession];
}

Create a session object in the view controller’s viewDidLoad method as shown above. The session object we created is fine for our example, but you probably want a bit more flexibility in most cases. The session object we just created uses the global NSURLCache, NSHTTPCookieStorage, and NSURLCredentialStorage. This means that it works pretty similar to a default implementation of NSURLConnection.

Step 3: Create a Data Task

To put the session object to use, let’s query the iTunes Store Search API and search for software made by Apple. The iTunes Store Search API is easy to use and requires no authentication, which makes it ideal for our example.

To query the search API, we need to send a request to https://itunes.apple.com/search and pass a few parameters. As we saw earlier, when using the NSURLSession API, a request is represented by a task. To query the search API, all we need is a data task, an instance of the NSURLSessionDataTask class. Take a look at the updated viewDidLoad implementation shown below.

- (void)viewDidLoad {
    [super viewDidLoad];
    NSURLSession *session = [NSURLSession sharedSession];
    NSURLSessionDataTask *dataTask = [session dataTaskWithURL:[NSURL URLWithString:@"https://itunes.apple.com/search?term=apple&media=software"] completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
        NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
        NSLog(@"%@", json);
    }];
}

There are a number of methods available to create a task, but the key concept to understand is that the session object does the actual creation and configuration of the task. In this example, we invoke dataTaskWithURL:completionHandler: and pass it an instance of NSURL as well as a completion handler. The completion handler accepts three arguments, the raw data of the response (NSData), the response object (NSURLResponse), and an error object (NSError). If the request is successful, the error object is nil. Because we know the request returns a JSON response, we create a Foundation object from the data object that we’ve received and log the output to the console.

It is important to understand that the error object passed to the completion handler is only populated, not nil, if the request failed or encountered an error. In other words, if the request returned a 404 response, the request did succeed as far as the sessions is concerned. The error object will then be nil. This is an important concept to grasp when working with NSURLSession and NSURLConnection for that matter.

Build the project and run the application in the iOS Simulator or on a physical device, and inspect Xcode’s Console. Nothing is printed to the console. What went wrong? As I mentioned earlier, the NSURLSession API supports pausing, canceling, and resuming of tasks or requests. This behavior is similar to that of NSOperation and it may remind you of the AFNetworking library. A task has a state property that indicates whether the task is running (NSURLSessionTaskStateRunning), suspended (NSURLSessionTaskStateSuspended), canceling (NSURLSessionTaskStateCanceling), or completed (NSURLSessionTaskStateCompleted). When a session object creates a task, the task starts its life in the suspended state. To start the task, we need to tell it to resume by calling resume on the task. Update the viewDidLoad method as shown below, run the application one more time, and inspect the output in the console. Mission accomplished.

- (void)viewDidLoad {
    [super viewDidLoad];
    NSURLSession *session = [NSURLSession sharedSession];
    NSURLSessionDataTask *dataTask = [session dataTaskWithURL:[NSURL URLWithString:@"https://itunes.apple.com/search?term=apple&media=software"] completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
        NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
        NSLog(@"%@", json);
    }];
    [dataTask resume];
}

Downloading a Remote Resource

In the previous example, we made use of a completion handler to process the response we received from the request. It’s also possible to achieve the same result by implementing the task delegate protocol(s). Let’s see what it takes to download an image by leveraging NSURLSession and the NSURLSessionDownloadTask.

Step 1: Create the User Interface

Open MTViewController.h and create two outlets as shown below. We’ll use the first outlet, an instance of UIImageView, to display the downloaded image to the user. The second outlet, an instance of UIProgressView, will show the progress of the download task.

#import <UIKit/UIKit.h>
@interface MTViewController : UIViewController
@property (weak, nonatomic) IBOutlet UIImageView *imageView;
@property (weak, nonatomic) IBOutlet UIProgressView *progressView;
@end

Open the project’s main storyboard (Main.storyboard), drag a UIImageView instance to the view controller’s view, and connect the view controller’s outlet that we just created in the view controller’s header file. Repeat this process for the progress view.

Configure the application's user interface.

Step 2: Create a Download Task

In this example, we won’t make use of the sharedSession class method, because we need to configure the session object that we’ll use to make the request. Update the implementation of viewDidLoad as shown below.

- (void)viewDidLoad {
    [super viewDidLoad];
    NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];
    NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfiguration delegate:self delegateQueue:nil];
    NSURLSessionDownloadTask *downloadTask = [session downloadTaskWithURL:[NSURL URLWithString:@"http://cdn.tutsplus.com/mobile/uploads/2013/12/sample.jpg"]];
    [downloadTask resume];
}

To prevent any compiler warning from popping up, make sure to conform the MTViewController class to the NSURLSessionDelegate and NSURLSessionDownloadDelegate protocols as shown below.

#import "MTViewController.h"
@interface MTViewController () <NSURLSessionDelegate, NSURLSessionDownloadDelegate>
@end

In viewDidLoad, we create an instance of the NSURLSessionConfiguration class by invoking the defaultSessionConfiguration class method. As stated in the documentation, by using the default session configuration the session will behave much like an instance of NSURLConnection in its default configuration, which is fine for our example.

In this example, we create a NSURLSession instance by invoking the sessionWithConfiguration:delegate:delegateQueue: class method and pass the sessionConfiguration object we created a moment ago. We set the view controller as the session delegate and pass nil as the third argument. You can ignore the third argument for now. The main difference with the previous example is that we set the session‘s delegate to the view controller.

To download the image, we need to create a download task. We do this by calling downloadTaskWithURL: on the session object, passing an instance of NSURL, and calling resume on the download task. We could have made use of a completion handler like we did earlier, but I want to show you the possibilities of using a delegate instead.

Step 3: Implement the Delegate Protocol

To make all this work, we need to implement the three delegate methods of the NSURLSessionDownloadDelegate protocol, URLSession:downloadTask:didFinishDownloadingToURL:, URLSession:downloadTask:didResumeAtOffset:expectedTotalBytes:, and URLSession:downloadTask:downloadTask didWriteData:totalBytesWritten:totalBytesExpectedToWrite:. The implementation of each method is quite easy. It’s important to note that we need update the user interface on the main thread using GCD (Grand Central Dispatch). By passing nil as the third argument of sessionWithConfiguration:delegate:delegateQueue:, the operating system created a background queue for us. This is fine, but it also means that we need to be aware that the delegate methods are invoked on a background thread instead of the main thread. Build the project and run the application to see the result of our hard work.

- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location {
    NSData *data = [NSData dataWithContentsOfURL:location];
    dispatch_async(dispatch_get_main_queue(), ^{
        [self.progressView setHidden:YES];
        [self.imageView setImage:[UIImage imageWithData:data]];
    });
}
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes {
}
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite {
    float progress = (double)totalBytesWritten / (double)totalBytesExpectedToWrite;
    dispatch_async(dispatch_get_main_queue(), ^{
        [self.progressView setProgress:progress];
    });
}

Conclusion

With these two examples, you should have a basic understanding of the fundamentals of the NSURLSession API, how it compares to NSURLConnection, and what its advantages are. In the next part of this series, we will look at more advanced features of NSURLSession.

Android SDK: Detecting Gestures

$
0
0

The Android SDK supports a variety of gestures you can detect, allowing you to tailor the ways in which users interact with your applications. In this tutorial, we will look at the framework that allows developers to add gesture detection to a simple application, working through the process of supporting the fling gesture and outlining how to support other gestures. Once you’ve completed the development for a basic fling function, you’ll be able to add additional gestures to the application yourself.


1. Create a New Application

Step 1

To demonstrate gesture detection in Android, we will build a simple application to display messages to the user. The user will be able to cycle forward and backward through the messages using the fling gesture, which involves swiping a finger or stylus across the screen from left to right or right to left. In reality, with this type of application, the message content would typically be read from a data source, but to simplify the task we will simply store the messages in an array. Create a new Android project and let Eclipse create a main Activity class for it with a main layout.

Open the layout of the application and use the following basic content. It is fine to leave the default parent layout added by Eclipse in place and simply adjust the contained TextView to match the one below.

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:tools="http://schemas.android.com/tools"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:paddingBottom="@dimen/activity_vertical_margin"
  android:paddingLeft="@dimen/activity_horizontal_margin"
  android:paddingRight="@dimen/activity_horizontal_margin"
  android:paddingTop="@dimen/activity_vertical_margin"
  tools:context=".MainActivity" ><TextView
    android:id="@+id/the_message"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" /></RelativeLayout>

If necessary, modify the name of the main class listed as tools:context attribute for the layout to suit your own main Activity class. The layout includes a TextView with an id attribute so that we can refer to it in the implementation of the Activity class.

Step 2

This gives us a basic layout with a text view for displaying the messages. We can now implement the Activity class. Start by opening the class and inspecting its contents.

import android.os.Bundle;
import android.app.Activity;
public class MainActivity extends Activity {
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
  }
}

Add the following import statements to the list at the top of the class implementation.

import android.support.v4.view.GestureDetectorCompat;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.widget.TextView;

2. Prepare the User Interface

Step 1

Let’s prepare the application for displaying messages. Add the following instance variables before the onCreate method.

//message text view
private TextView messageView;
//message array
private String[] messages;
//total messages
private int numMessages = 10;
//current message -start at zero
private int currMessage = 0;

As mentioned earlier, you wouldn’t normally hard code data into an application, but we will do so in this case so that we can focus on detecting gestures, the main subject of this tutorial. We have a variable that keeps a reference to the text view we added to the layout, an array for the messages, a variable to record the total number of messages, and a counter to keep track of which message is currently being displayed.

Step 2

Inside the onCreate method immediately after the line setting the content view, retrieve a reference to the text view using its id and store a reference in messageView as shown below.

messageView = (TextView)findViewById(R.id.the_message);

In the next code snippet, we instantiate the messages array.

messages = new String[numMessages];

For simplicity, let’s make each message some dummy text containing a number so we can easily see which message is being displayed.

for(int i=0; i<numMessages; i++){
  messages[i]="Message "+i+":\n\n"+"Here is message "+i+":\n\n"+"Lorem ipsum dolor sit amet, consectetur adipisicing elit, "
      + "sed do eiusmod tempor incididunt ut labore et dolore magna "
      + "aliqua. Ut enim ad minim veniam, quis nostrud exercitation "
      + "ullamco laboris nisi ut aliquip ex ea commodo consequat. "
      + "Duis aute irure dolor in reprehenderit in voluptate velit "
      + "esse cillum dolore eu fugiat nulla pariatur. Excepteur sint "
      + "occaecat cupidatat non proident, sunt in culpa qui officia "
      + "deserunt mollit anim id est laborum.";
}

After the loop, set tell the text view to display the first message of the messages array.

messageView.setText(messages[currMessage]);

3. Detect Gestures

Step 1

You have a few options when it comes to preparing your activity classes to detect gestures. You can set up gesture detection on individual views in your application by setting an onTouchListener on them, with the onTouch method implemented inside your touch listener. To allow the activity as a whole to detect gestures, you can make the class implement the GestureDetector interface(s) and supply methods for each gesture. Possible gestures include onDoubleTap, onDown, onFling, onLongPress, onScroll, onShowPress, and onSingleTapUp. See Detecting Common Gestures in the Developer Guide for possible options.

If you only want to support a subset of gestures, you can use the more convenient option we will demonstrate in this tutorial, that is, adding a class that extends SimpleOnGestureListener. By doing so, the class handles any gestures you are not supplying explicit instructions for in your overridden methods.

Add an inner class declaration inside your activity class, after the onCreate method, extending SimpleOnGestureListener.

public class GestureListener extends GestureDetector.SimpleOnGestureListener {
//class content
}

Inside this class, we will define what should happen when a particular gesture is detected, the fling gesture in our example.

Step 2

Although we are primarily interested in the fling gesture, when using SimpleOnGestureListener you need to implement the onDown method at a minimum, since the system may otherwise ignore remaining gesture events. Add the method inside your new inner class as shown below.

@Override
public boolean onDown(MotionEvent event) {
  return true;
}

Returning true tells the operating system that your code is interested in the remaining gesture events. After onDown, add a stub implementation for the onFling method. We will discuss its implementation a bit later in this tutorial.

@Override
public boolean onFling(MotionEvent event1, MotionEvent event2,
    float velocityX, float velocityY) {
  //determine what happens on fling events
}

Step 3

Before we get to work on the detail of what should happen when the fling gesture is detected, we need to complete gesture detection for the class. Add an instance variable for a gesture detector at the top of the activity class, before the onCreate method.

//gesture detector
private GestureDetectorCompat gDetect;

Inside the onCreate method and after the existing code, instantiate the gesture detector by passing an instance of the new class we created.

gDetect = new GestureDetectorCompat(this, new GestureListener());

After the onCreate method, we need to override the onTouchEvent method to ensure that the gesture listener is used when a touch events is detected.

@Override
public boolean onTouchEvent(MotionEvent event){
  this.gDetect.onTouchEvent(event);
  return super.onTouchEvent(event);
}

The method calls the onTouchEvent method for the gesture detector, which will fire the appropriate gesture methods inside the inner class. Next, we will focus on the detail of what will happen when the user flings the messages in our application, but take a moment to look at the structure of your class for future reference. This is an approach you can use for supporting a set of gestures in any activity, that is, adding an inner class to extend SimpleOnGestureListener, overriding onTouchEvent to call the onTouchEvent method for a gesture detector you instantiated using an object of your SimpleOnGestureListener class.


4. Fling Messages

Step 1

Finally, we can focus on what happens when the fling gesture is detected. In your inner class, start by adding a couple of variables we need to offset the calculations for optimum reliability (before the onDown and onFling methods).

private float flingMin = 100;
private float velocityMin = 100;

In your own applications, you may find the need to tweak these values to suit your interaction models. Inside onFling, declare two boolean variables to keep track of the direction the messages are moving in.

//user will move forward through messages on fling up or left
boolean forward = false;
//user will move backward through messages on fling down or right
boolean backward = false;

We will interpret flings to the left or up as a desire to move forward and flings down or to the right as a desire to move backwards through the messages. This is a common UX paradigm in messaging and email applications.

Step 2

Note that the onFling method receives four parameters, representing the down and move motions that triggered the event and the velocity of the gesture in x and y directions. We’ll use these parameters to determine the direction of the fling. We then calculate the x and y differences for the two motion events.

//calculate the change in X position within the fling gesture
float horizontalDiff = event2.getX() - event1.getX();
//calculate the change in Y position within the fling gesture
float verticalDiff = event2.getY() - event1.getY();

Now calculate the absolute values for these measures as well as the velocity values.

float absHDiff = Math.abs(horizontalDiff);
float absVDiff = Math.abs(verticalDiff);
float absVelocityX = Math.abs(velocityX);
float absVelocityY = Math.abs(velocityY);

Step 3

We only want to respond to the fling gesture if it exceeds the offset values we defined. Start with the case where the horizontal difference is greater than the vertical difference.

if(absHDiff>absVDiff && absHDiff>flingMin && absVelocityX>velocityMin){
//move forward or backward
}

Inside the if block, set the boolean variables according to whether the user gesture indicates a forward or backward motion.

if(horizontalDiff>0) backward=true;
else forward=true;

Still inside the onFling method, after the outer if statement, add an else if for cases where the horizontal difference is not greater than the vertical one.

else if(absVDiff>flingMin && absVelocityY>velocityMin){
  if(verticalDiff>0) backward=true;
  else forward=true;
}

We check once more that the values exceed the minimum thresholds we defined earlier so that we only respond to gestures that can reasonably be interpreted as fling gestures. Again, we set the forward or backward variable to true.

Step 4

Still inside onFling, update the displayed message according to the user gesture.

//user is cycling forward through messages
if(forward){
  //check current message is not at end of array
  //increment or set back to start
  if(currMessage<numMessages-1) currMessage++;
  else currMessage = 0;
  //set the message text display
  messageView.setText(messages[currMessage]);
}
//user is cycling backwards through messages
else if(backward){
  //check that current message is not at start of array
  //decrement or set to last message
  if(currMessage>0) currMessage--;
  else currMessage = numMessages-1;
  //set the message text display
  messageView.setText(messages[currMessage]);
}

If the gesture indicates that the user is moving forward through the messages, we first check if they are already at the last message, incrementing the variable or setting it back to the first message and we then set the message text to display. If the user is moving backwards through the messages, we check if the first message is currently being displayed, decrementing the variable or setting it to the last message.

Finish the onFling method implementation by returning true.

return true;

You can now test your application by running it on an actual device or in the emulator. Flinging to the left or up will display the next message, while moving to the previous message when flinging to the right or down.

Flinging Messages
The application after flinging to the left or down three times from launch.

Conclusion

In this tutorial, we explored adding gesture detection to an Android application, creating the structures you need in your activity classes, and working through a simple example using the fling gesture. Take a look at the source code of this tutorial if you are unsure about any of the instructions. If you want to explore gestures in more detail, extend the code you created to support other gestures in your application. As you can see, adding support for detecting gestures gives you a fine level of control over the user experience within your applications, although which gestures you need to handle will naturally depend on the functionality of the application.

Android 4.4 KitKat: What’s New

$
0
0

Google released its latest version of Android on October 31, 2013. The new release, version 4.4, is nicknamed KitKat. The release came as a surprise to many as Key Lime Pie and 5.0 had been linked to this update for quite some time. KitKat, however, doesn’t disappoint as it’s packed with features and updates. In this article, I’ll give you an overview overview of what’s new in KitKat.


Visual Changes

Before discussing the visual changes introduced in KitKat, it is good to know that not all visual changes are present on every KitKat-compatible device. The Nexus 5, Google’s flagship smartphone that was introduced alongside KitKat, includes all the visual changes discussed below. The experience on other devices, however, can vary.

At first glance, KitKat doesn’t look particularly different from Jelly Bean. However, a lot has changed to simplify the user interface and focus on content.

  • The blue color used in the system bar and menus has been replaced with a milky white.
  • The Wallpaper application is present in the application launcher.
  • Some of the application icons have adopted a monochromatic look.
  • Widgets can be accessed by long pressing the home screen.
  • The lock screen can now display album and film art.
  • Home screens are infinite in size.

The most significant change and the one that received little attention is how the home screen has been moved to the Google Search application. There’s a great article on Ars Technica that goes into more detail on this change.



New Apps

KitKat made some changes to the application line-up.

Phone

The phone application has had significant work done to it. The dialer is essentially the same, but the main screen now shows and organizes your contacts based on the people you talk to the most. It also integrates search features allowing you to search for contacts, local businesses, and places. Caller identification has also been improved. The operating system will try and identify unknown numbers by searching local businesses.

Hangouts

Hangouts has added support for text messages to its already rich feature set.

Play Books

Play Books has been changed to showcase the new immersive mode.

Emoji

Emoji characters are now available from the Google keyboard.

Quick Office

Quick Office received a redesign and is now integrated with Google Drive. If Quick Office and Google Drive are both present on the device, Google Docs, Slides, and Sheets will open in Google Drive from Quick Office.

Google Now

Google Now has added its OK Google feature. It’s currently only available to certain devices, but this will change as time goes on. The feature itself let’s you start a search or perform a command by saying OK Google followed by a query or command. Your device doesn’t to be on the home screen or in Google Now for this to work.

Gmail

The popular email platform also received a number of updates, including a vacation responder and attachment support for many file types.

Device Management

Device Manager was showcased at Google I/O 2013 as part of the ambitious overhaul of Play Services. It is Google’s answer to theft and other security concerns. Device Manager is built into Android 4.4 and it is by default configured to locate and wipe the device.

Downloads

The Downloads application has improved as well. It has the ability to sort and display downloads in a grid.


Under the hood

Project Svelte

Project Svelte was the internal code name for KitKat. Its goals were to reduce the size of the operating system and to improve the operating system’s performance on low-end devices. The result is that KitKat can run on devices with only 512MB of RAM and everything has been geared towards memory optimization, including a new API to aid in making applications more memory efficient.

Memory Management Tools

To help developers optimize their applications, Google released new tools for monitoring an application’s memory usage. Procstats is one of those tools. It analyses the memory resources that an application uses as well as the memory being used by other applications and services on the system. The tool can be used via ADB like so, adb shell dumpsys procstats.

Another addition is the on-device memory status and profiling. It can be accessed from Settings > Developer options > Process stats.


Printing Framework

KitKat introduces a native printing framework. It exposes a print manager that connects applications that require printing and available print services. The print manager exposes a shared service and a system user interface. The result is a consistent user interface for printing documents as well as security since the content is passed between services.

Vendors can also use the new APIs to create their own print services and third-party developers can use the APIs to add printing functionality to their own applications with a few lines of code. For more information, take a look at this DevBytes video.

Storage Access Framework

Android 4.4 also introduced a brand new storage access framework. The goal is twofold, (1) allow users to browse files, images, and videos across the available storage provides and (2) present this in a consistent user interface. The accompanying API gives applications the ability to publish their services to other applications that participate in the framework. Client applications that want to leverage the storage access framework can integrate with it using the CREATE_DOCUMENT and OPEN_DOCUMENT intents.

Full Screen Immersive Mode

This addition allows an application to take up every pixel on the screen while hiding the system user interface and the status bar at the top. Read more about this new feature at DevBytes.

WebView Component

KitKit also sports an updated WebView component, which is based on the Chromium open source project. It improves support for modern web standards and the V8 JavaScript engine received an update as well. Another important change is the rendering engine. The new WebView component uses the same Blink rendering engine as Chrome for Android does. The result is that you’ll notice less inconsistencies between the WebView component and Chrome for Android.

Screen Recording

KitKat introduces a screen recording utility that can be used via ADB like so, adb shell screenrecord. The utility records at a resolution as close to the device’s screen resolution as possible.

NFC Enhancements

KitKat introduces HCE or Host Card Emulation, which allows any application to emulate an NFC (Near Field Communication) smart card. An NFC controller must be present in the device.

SMS Provider

If you have an application that makes use of both SMS and MMS, you can make use of the shared SMS provider and the new APIs to manage your application’s message storage and retrieval.

Enhanced Notification Access

In KitKat, The notification listener service can see more information about incoming notifications. The listener service can access extra information, including text, icon, picture, progress, and chronometer.

Audio Tunneling

Because audio tunneling requires a DSP or digital signal processor, not every device will support this feature. The idea is to offload audio-related tasks to a digital signal processor instead of the CPU. The result is that audio tunneling to DSP increases battery life dramatically.

IR Blasters

KitKat introduces support for built-in IR blasters with an accompanying API. The API allows the application to check whether the device has an IR emitter, query its frequency, and send signals.

Transitions

Android 4.4 introduces a Transitions framework allowing an application to define scenes and specify how to animate between scenes. Take a look at this video for a demonstration.

Force RTL Layout

Testing RTL (Right to Left) issue, has always been cumbersome. To improve this, KitKat has an option to enforce the layout into RTL without the need to display your application in an RTL language. You can find the setting in Settings > Developer Options > Force RTL layout direction.

Additional Features

  • Improvements to HTTP Live Streaming
  • Common Encryption for DASH
  • Audio Monitoring
  • Loudness Enhancer
  • Audio Timestamps for Improved AV Sync
  • Performance Improvements to the RenderScript Runtime
  • GLES2.0 SurfaceFlinger
  • New Hardware Composer support for Virtual Displays
  • New Bluetooth Profiles
  • Wi-Fi TDLS Support
  • Chromecast Support
  • Enhanced Accessibility APIs
  • Resolution Switching Through Adaptive Playback
  • Translucent System UI Styling
  • Drawable Mirroring for RTL Locales
  • Improved Cryptographic Algorithms

API Round-Up

API 19 added six new packages (see below).

  • android.graphics.pdf
  • android.nfc.cardemulation
  • android.print
  • android.print.pdf
  • android.printservice
  • android.transition

Another 49 packages were updated. You can find the complete changelog at the Android Developers website.


Adoption

Even though KitKat is a point release, it has significantly improved Android with a number of great features. Some of the new features are currently only supported by the Nexus 5 as they are hardware-related, but this will change over time as new handsets are released with support for KitKat. As of December 2, 2013, KitKat made up 1.1% of Android distributions with over 50% being taken up by Jelly Bean.



Conclusion

The key question with regards to the next Android release is the version number. Will it be Android 4.5 or 5.0. If Google maintains its naming scheme, the next release will start with the letter L. Will it be Lemonade? Who knows.

Corona SDK: Make a Word Drop Game

$
0
0

In this tutorial, I’ll teach you how to create a Word Drop game using the Corona SDK. We’ll build the game from start to finish so I encourage you to follow along. In this tutorial, we will work with timers, physics, and implement our own touch controls. Let’s get started.


Introduction

The objective of the game is to create words from the lettered balls. If the balls cross the bar at the top, the game is over. You have three bombs, which you can use to remove five balls so it is key to use them sparingly. Every ten seconds, more balls drop from the top of the screen. Take a look at the screenshot to get an idea of the game.

gamescreen

1. New Project

Open the Corona Simulator and choose New Project.

CoronaSDK_BlackBox_15

On the next screen, apply the following settings.

settings

Click Next and choose Open in Editor. This will open Main.lua in your text editor of choice.


2. Project Configuration

Open Config.lua and replace the file’s contents with the configuration shown below. This will set the project’s default width, height, scale, and FPS (frames per second). The letterBox scale setting means that the application will scale up in both directions as uniformly as possible. If necessary, however, the game will be letterboxed.

application = {
   content = {
     width = 320,
     height = 480,
     scale = "letterBox",
     fps = 30,
   }
}

3. Hiding the Status Bar

To prevent the status bar from being shown at the top of the screen, add the following snippet to Main.lua.

display.setStatusBar(display.HiddenStatusBar)

4. Local Variables

In the following code snippet, you can see a listing of the variables that we’ll be using in this game. Read the comments get an idea of each variable’s responsibility.

local gameBackground = display.newImage("background.png",true)
local theWord = "" -- the word the user spells
local theWordText -- shows the word
local isNewGame = true
local allBallsGroup -- group to hold all the balls
local wordTable = {} -- will hold the words from the text file
local chosenBalls = {} -- holds the balls the user has chosen
local instructionsText -- shows instructions
local countDownText -- shows the time
local numBallsToGenerate = 10 -- how many balls to generate
local allBalls = {} -- holds all the balls that have been generated
local theBombs = {} -- holds references to the bomb image
local generateBallTimer -- timer for generating balls
local clockTimer -- timer for the clock
local gameTime = 10 -- how many seconds before new balls drop

5. Setting Up the Physics

With the following snippet, we require and start the physics engine. We set the gravity high to make sure that the balls drop fast.

local physics = require("physics")
physics.start(true)
physics.setGravity(0,50)

6. setup

In setup, we seed the random generator to ensure math.random generates a random number when we need one.

function setup()
    math.randomseed(os.time())
end

Call setup immediately after its declaration.

setup()

7. setupGameAssets

In the next few steps, we will stub out a number of functions, which we will implement a bit later in this tutorial.

In setupGameAssets, the assets of the game are set up.

function setupGameAssets()
end

8. newGame

The newGame function is responsible for starting a new game.

function newGame()
end

9. setupGameBoundaries

In setupGameBoundaries, the boundaries for the balls at the left, right, and bottom of the screens are set.

function setupGameBoundaries()
end

10. setupButtons

The setupButtons function sets up the buttons.

function setupButtons()
end

11. setupTextFields

In setupTextFields, the text fields are set up.

function setupTextFields()
end

12. setupBombs

This function sets up the images for the bombs.

function setupBombs()
end

13. setBombsVisible

By invoking setBombsVisible, the bombs are set to be visible.

function setBombsVisible()
end

14. setBombsInvisible

This functions needs no explaining. Right?

function setBombsInvisible()
end

15. generateBalls

The generateBalls function is responsible for generating new balls at regular time intervals.

function generateBalls()
end

16. startTimer

startTimer starts the timer.

function startTimer()
end

17. doCountDown

In doCountDown, the game time is decremented.

function doCountdown()
end

18. createBall

The createBall function is responsible for creating one ball. It takes one argument, the letter the ball contains.

function createBall(createVowel)
end

19. checkGameOver

In checkGameOver, we verify if the game is over, that is, if the wall of balls has crossed the bar at the top of the screen.

function checkGameOver()
end

20. checkWord

In checkWord, we verify if the word the user spelled is valid.

function checkWord()
end

21. resetWord

The resetWord function is invoked when the player cancels a submission.

function resetWord()
end

22. createVowelBalls

The createVowelBalls function ensures that some of the balls contain a vowel. It takes one parameter, the number of balls that should contain a vowel.

function createVowelBalls(number)
end

23. formString

This function creates a string from the letters on the balls that the user has chosen.

function formString(e)
end

24. explode

The explode function is invoked when the player uses a bomb. It removes five balls from the game.

function explode(e)
end

25. removeBall

The removeBall function chooses a random ball to remove from the game.

function removeBall()
end

26. readTextFile

The readTextFile function is used to read a text file and store the words it contains in a table for use in the game.

function readTextFile()
end

27. Progress Check

Double-check that you’ve created stub implementations for the above functions before moving on. In the next few steps, we’ll implement each function.


28. Implementing readTextFile

In readTextFile, we read the text file from the resource directory and store each word in wordTable. We make use of string.sub to trim whitespace from the end of each word.

local path = system.pathForFile( "wordlist.txt", system.ResourceDirectory)
local file = io.open( path, "r" )
for line in file:lines() do
   line = string.sub(line,
       1, #line - 1)
    table.insert(wordTable,line)
end
io.close( file )
file = nil

readTextFile is invoked in setupGameAssets as shown below. We’ll be updating setupGameAssets a few more time later in this tutorial.

function setupGameAssets()
  readTextFile()
end

29. Implementing setupGameBoundaries

In setupGameBoundaries, the boundaries for the game are defined. lineLeft and lineRight are the right and left boundaries, whereas groundLine is the bottom of the screen, the ground so to speak. These are used by the physics engine and will prevent the balls from moving outside of the game area. We set them to not be visible because we do not need to see them. The reason we’ve used -29, is because, the radius of the balls is 29 and the physics system uses the center of objects when testing for collision.

local groundLine = display.newRect(0, 380,display.contentWidth, 2)
local lineLeft = display.newRect(-29,0,2,display.contentHeight)
local lineRight = display.newRect(display.contentWidth-29,0,2,display.contentHeight)
physics.addBody(groundLine, 'static',{bounce=0,friction=0})
physics.addBody(lineLeft, 'static',{bounce=0,friction=0})
physics.addBody(lineRight,'static',{bounce=0,friction=0})
groundLine.isVisible = false
lineLeft.isVisible = false
lineRight.isVisible = false

Just like readTextFile, setupGameBoundaries is invoked in setupGameAssets.

function setupGameAssets()
  readTextFile()
  setupGameBoundaries()
end

30. Implementing setupButtons

Implement setupButtons as shown below and invoke the function in setupGameAssets.

local goButton = display.newImage("goButton.png",260,420)
goButton:addEventListener('tap', checkWord)
local stopButton = display.newImage("stopButton.png",5,430)
stopButton:addEventListener('tap',resetWord)
local bar = display.newImage("bar.png",0,100)
function setupGameAssets()
  readTextFile()
  setupGameBoundaries()
  setupButtons()
end

31. Implementing setupTextFields

Implement setupTextFields as shown below and invoke the function in setupGameAssets.

countDownText = display.newText(gameTime,290,10,native.systemFontBold,20)
countDownText:setTextColor("#000000")
theWordText = display.newText("",60,437,native.systemFontBold,25)
theWordText:setTextColor("#000000")
instructionsText = display.newText("",0,0,native.systemFontBold,25)
instructionsText.x = display.contentWidth/2
instructionsText.y = display.contentHeight/2
instructionsText:setTextColor("#000000")
function setupGameAssets()
  readTextFile()
  setupGameBoundaries()
  setupButtons()
  setupTextFields()
end

32. Implementing setupBombs

Implement setupBombs as shown below and invoke the function in setupGameAssets. In setupBombs, we generate three bomb images. By storing the images in a table, we can reference them without having to declare three separate image variables.

for i=1, 3 do
    local tempBomb = display.newImage("bomb.png")
    tempBomb.width = 30
    tempBomb.height = 30
    tempBomb.x =  33 * i
    tempBomb.y = 20
    tempBomb:addEventListener('tap', explode)
    table.insert(theBombs,tempBomb)
end
function setupGameAssets()
  readTextFile()
  setupGameBoundaries()
  setupButtons()
  setupTextFields()
  setupBombs()
end

33. Finishing setupGameAssets

Finalize the implementation of setupGameAssets by adding the snippet shown below. It initializes the group for the balls.

allBallsGroup = display.newGroup();

34. Finishing setup

With the setupGameAssets function ready to use, we can invoke it in the setup function as shown below.

function setup()
    math.randomseed(os.time())
    setupGameAssets()
end

35. Implementing createBall

We have two tables, one for the alphabet and one only for vowels as we want to ensure that some of the balls contain vowels. We then generate random values for the ballType and ballSize variables. The value of ballType ranges from 1 to 4, whereas the value of ballSize ranges from 1 to 2. By using these variables, we get a ball color and set its radius. The letterText uses the random letter we generated and sets its x and y to be the same as the ball. We then insert both the letter and the ball in a group so they appear as one element in the game. Next, we generate a random x position for the ball and place it at -40 for the y position. We add physics to the ball to make sure it falls from the top of the screen to the bottom. Give it name and letter keys, add a tap event, and insert it into the allBalls table as well as the allBallsGroup table. The latter enables us to work with all the balls currently in the game.

local var alphabetArray = {"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"}
local vowels = {"A","E","I","O","U"}
local ballType = math.random(4)
local ballSize = math.random(2)
local letterIndex
local letter
    if(createVowel == true) then
     letterIndex = math.random(#vowels)
     letter = vowels[letterIndex]
    else
   letterIndex = math.random(#alphabetArray);
   letter = alphabetArray[letterIndex]
    end
local ballGroup = display.newGroup();
local ball
local ballRadius
    if(ballType == 1) then
  ball = display.newImage("greenBall.png")
    elseif(ballType == 2) then
  ball = display.newImage("brownBall.png")
  elseif(ballType == 3) then
       ball = display.newImage("pinkBall.png")
  else
       ball = display.newImage("redBall.png")
    end
    if(ballSize == 1)then
    ball.width  = 48
    ball.height = 48
    ballRadius = 24
    else
      ball.width = 58
      ball.height = 58
      ballRadius = 29
    end
local letterText = display.newText( letter, 0,0, native.systemFontBold, 25 );
letterText:setTextColor(0,0, 0)
letterText.x = ball.x
letterText.y = ball.y
ballGroup:insert(ball)
ballGroup:insert(letterText)
ballGroup.x = math.random(ballRadius,display.contentWidth-ballRadius*2)
ballGroup.y= - 40
physics.addBody(ballGroup, 'dynamic',{friction = 0,bounce = 0,radius = ballRadius})
ballGroup.name = "ball"
ballGroup.letter = letter
ballGroup:addEventListener('tap',formString)
table.insert(allBalls,ballGroup)
allBallsGroup:insert(ballGroup)

If you invoke this function in setup, you should see one ball being created and fall from the top of the screen to the bottom. Don’t forget to remove the call form the setup method when you’re done testing.


36. Implementing generateBalls

In generateBalls, we invoke checkGameOver after 1500 milliseconds, which gives the balls enough time to fall past the bar. If it’s a new game, we need to generate ten balls, otherwise we generate four balls of which at least one contains a vowel. We’ll explore the implementation of createVowelBalls shortly. If you invoke generateBalls in setup, you should see ten balls being generated.

function generateBalls()
  timer.performWithDelay(1500,checkGameOver)
  if(isNewGame == true) then
    numBallsToGenerate = 10
  else
    numBallsToGenerate = 4
    createVowelBalls(1)
  end
  generateBallTimer = timer.performWithDelay( 50, createBall, numBallsToGenerate)
end

37. Implementing createVowelBalls

All this function does is invoke createBall as many times as the value of number that was passed to the function. We pass true as the parameter, which means createBall will generate a ball containing a vowel.

for i=1, number do
   createBall(true)
end

38. Implementing removeBall

This function chooses a random ball from the allBalls table and removes it. This function is invoked by the explode function, which we’ll implement in a few moments.

local randomIndex = math.random(#allBalls)
local tempBall = allBalls[randomIndex]
tempBall:removeSelf()
tempBall = nil
table.remove(allBalls,randomIndex)

39. Implementing setBombsVisible

In setBombsVisible, we loop through the bombs and setting them to visible.

for i=1, #theBombs do
    theBombs[i].isVisible = true
end

40. Implementing setBombsInvisible

In this function, we do the exact opposite as we did in setBombsVisible.

for i=1, #theBombs do
   theBombs[i].isVisible = false
end

41. Implementing explode

In explode, we check whether allBalls contains less than five balls. If less than five balls are present, we remove all balls, otherwise we only remove five balls.

local thisSprite = e.target
thisSprite.isVisible = false
local randomIndex
local randomBall
 if(#allBalls < 5) then
     for i=1, #allBalls do
  removeBall()
     end
else
    for i=1, 5 do
  removeBall()
   end
end

42. Implementing formString

In formString, we form a word every time the user clicks a ball. Remember that each ball has a letter key added to it. We check whether the chosenBalls table doesn’t contain the ball they tapped on. If it doesn’t, we insert the ball into the chosenBalls table, tack the letter onto the end of theWord variable, and show it in the text field. If the ball was already chosen and added to chosenBalls, we don’t add it to chosenBalls and print a message to the console instead. You can already test our game by tapping some balls and seeing the word appear in the text field.

local thisSprite = e.target
local theLetter = thisSprite.letter
if(table.indexOf(chosenBalls,thisSprite) == nil) then
    table.insert(chosenBalls,thisSprite)
    theWord = theWord .. theLetter
    theWordText.text = theWord
    theWordText.x = display.contentWidth/2
else
   print("already chose that ball")
end

43. Implementing resetWord

instructionsText.text = "";
theWord = ''
theWordText.text = ""
chosenBalls = {}

This function resets the current word and clears out the chosenBalls table. If you test the game, you can click the cancel button to clear out the text field.


44.Implementing checkWord

In checkWord, we check if the length of theWord is less than or equal to one. If it is, we return from the function. We need to make sure the player has chosen a word with a minimum of two letters. We then need to check if theWord matches a word from the wordTable. If it doesn’t, we set the instructionsText to NOT A WORD and show it to the player. If it does, we loop through the chosenBalls table and remove each ball from the game.

if(#theWord <= 1) then
    return;
end
local lowerCaseWord = string.lower(theWord)
local tempBall
    if(table.indexOf(wordTable,lowerCaseWord) == nil) then
   instructionsText.text = "NOT A WORD!"
   instructionsText:toFront()
    else
    for i=1, #chosenBalls do
    table.remove(allBalls,table.indexOf(allBalls,chosenBalls[i]))
        chosenBalls[i]:removeSelf()
        chosenBalls[i] = nil
        theWord = ""
        theWordText.text = ""
end
chosenBalls = {}
end

45. Implementing doCountDown

In doCountDown, we grab the number from the text field, decrement it, and check if it is equal to zero. If it is, we call generateBalls, reset it, and call startTimer, which in turn invokes doCountDown.

local currentTime = countDownText.text
currentTime = currentTime -1
countDownText.text = currentTime
    if(currentTime == 0) then
  generateBalls()
  countDownText.text = gameTime
  startTimer()
end

46. Implmenting startTimer

The implementation of startTimer is simple. We call doCountdown every second and repeat this as many times as the value of gameTime.

clockTimer = timer.performWithDelay(1000,doCountdown,gameTime)

47. Implementing newGame

To start a new game, the variables we declared earlier are reset and startTimer is invoked to start the game.

isNewGame = true
chosenBalls = {}
allBalls = {}
theWord = ""
theWordText.text = ""
instructionsText.text = ""
countDownText.text = gameTime;
createVowelBalls(2)
generateBalls()
setBombsVisible()
startTimer()
isNewGame = false

48. Implementing checkGameOver

In this function, we loop through the allBalls table and check if the y value of any of the balls is greater than 100. If it is, one or more balls are crossing the bar at the top and the game is over. If the game is over, the balls are removed from the ballGroup table. The timers are canceled to make the bombs invisible and newGame is invoked after three seconds.

local gameOver = false;
    for i=1,#allBalls do
        if(allBalls[i].y < (100 - allBalls[i].height))then
            gameOver = true
            break;
  end
    end
if(gameOver) then
    for i=allBallsGroup.numChildren,1,-1 do
         local child = allBallsGroup[i]
         child:removeSelf()
         child = nil
    end
timer.cancel(generateBallTimer)
timer.cancel(clockTimer)
instructionsText.text = "GameOver"
instructionsText:toFront()
setBombsInvisible()
timer.performWithDelay(3000,newGame)

49. Finishing the Game

All that is left for us to do is calling newGame in the setup function.

function setup()
    math.randomseed(os.time())
    setupGameAssets()
    newGame()
end

Conclusion

In this tutorial, we created a creative word game. Feel free to experiment with the code we’ve written to see how it affects the game. I hope you found this tutorial helpful.


Mobile & Emotional Design

$
0
0

The process of designing an application, both functionally and aesthetically, has a large impact on how users feel about the final product. Emotional design can help to improve the user experience significantly. In this article, I will talk about what emotional design is, how you can apply it, and give some examples of applications that already implement emotional design.


What is Emotional Design?

Aesthetics have become increasingly important for the end user. It’s a common trend in software, hardware, and even for services. Everything begins with a functional and usable product. On top of that, you can enhance to provide a better experience for your users. This enhancement can provide pleasure and that is what we refer to as emotional design.

Remarkable products and services are the result of thinking how pleasure can be embedded into the product. The combination of an interesting concept, features, and design increases the chance of creating something successful and memorable. What are your favorite applications? And why? What have made them a success do you think?

Fun is a concept that is often used when referring to lasting memories, experiences, products, services, you name it. This can be applied to what you’re building for the App Store right now. The emotional design principles are applied in many of the applications we use daily.

A key aspect, besides pleasure, is branding. The creation of your unique voice, your personal identity within the digital space, makes it easier for your audience to fall in love with your product. Most of our favorite applications don’t have a neutral presence.


Humans Communicating with Humans

Products have a personality. If you see two coffee shops next to each other, both with the same prices and quality, it’s emotional design that convinces you to choose one over the other. We make a decision based on our impression and mood.

Duolingo
Duolingo applies emotional design to improve the experience of learning languages.

One of the key principles of emotional design is to make our communication human. As a user, we are continuously interacting with a machine to access the internet, its content, and other people. We might have the illusion we’re directly interacting with people, though, that’s not the case. It’s a machine that connects you with a human.

Good design in combination with thoughtful branding is able to create a human-like experience. Brands are able to create the illusion that you’re interacting with a personality. This makes a product more genuine and honest.

Even though this idea stems back from traditional marketing, the same ideas can be applied to digital design. Let’s take MailChimp as an example. They were able to create a strong, fun personality to accompany their product, which is pretty boring at first glance. I don’t think many people get excited about email newsletters.


Where Do I Start?

It all starts with your product and its key feature. The next step would be branding. Ask yourself, “If your product would be a person, what kind of characteristics would it have?” You can translate this directly to the unique identity of your product. The results of this translation are, for example, the logo, color scheme, copywriting, and art direction for the design. If you’re a developer and having trouble with this, consider hiring a seasoned designer to help you with this.

Second, before you go crazy on possible gimmicks, which could make your application fun, remember that every user has a number of basic needs to make using your application a positive experience. For example, think of consistent navigation and features without bugs. Usability is key before enhancing your application.

As a third step, you can focus on getting to know your users to create a better product. This is where you can start enhancing. Perhaps the model you had in mind for the navigation of your application is different from the one your users imagined. You have the opportunity to make the features of your application more remarkable and more fun. Some funny copy or an animated icon may surprise the user and make them smile. Instead of focusing on features, focus on the experience.


Learn About Human Behavior

Some insights into human behavior is very helpful when creating a better product. Here are a number of interesting techniques that are applied in emotional design.

  • By removing unnecessary elements and giving users a limited set of options, it’s easier to push users into taking action.
  • Once users have invested time in an application, it’s difficult for them to abandon the application. A technique used by many games.
  • Many applications try to create habits to improve user retention. For example, Shazam comes to mind when you hear a new song or Foursquare when you arrive at a new location.
  • Gamifying an application can improve its popularity. Popular examples are Duolingo, Foursquare, and Dropbox. However, this technique should be applied smartly.

What Can We Learn From Others?

yplan

Instagram

The emotional design in Instagram is content. It’s the users creating photos, sharing them, and discovering photos and other users. It’s a community-driven application and the experience is very human. That’s what’s so clever about Instagram, the emotional aspect is taken care of by the community. All Instagram does is providing a platform. The same applies to Tumblr.

Foursquare

Foursquare applies emotional design in the form of gamification. The user earns points by checking in at locations, which makes it easier to develop user habits, that is, checking in. Habits make it easier to make the transition to the core feature of the application, making users use the application on a regular basis to discover new places.

YPlan

Like Instagram, YPlan applies emotional design through content. Different from Instagram is the fact that YPlan curates the content for the user. It gives users a sense of involvement by asking them what kind of events they like. This is a win/win for both parties. Two other elements are the selection of photography to accompany events and the copy. YPlan tries to get people excited through a unique design and the use of curated content.

Duolingo

Duolingo is a great example of applied emotional design. The application showcases personality, has a mascot emphasizing that personality, implements gamification, and features a unique design to keep its users engaged. On top of that, it motivates user investment. The coach feature is a great example how to build user habits.

Day One

Day One

Day One is a wonderful application that has mastered emotional design. First of all, they clearly figured out a niche in the market. The paper diary didn’t have a powerful digital alternative. Day One solves that problem.

It works in two ways (1) the user provides their own content and (2) the application actively involves the user by providing a thought-provoking question on the Mac application. On the iPhone application, it tracks the steps of the user, its current activity, the music that’s playing in the background, etc.

In other words, the application tells the user what they were doing while making a diary entrance. This is a great example of how thinking about the original problem – as a human, I want to journal my day – can provide a solution, a solution the user wouldn’t have thought of. It’s a good example of learning and understanding human behavior and using design to create value.


Conclusion

It is well worth your time to improve your application by enhancing features, getting professional branding and design, and learn more about the user’s behavior. Emotional design isn’t just a nice theory. When applying emotion design and enhancing a product, it will increase the quality of the application. It can be in the form of tiny steps that make your users happier.


Resources

If you want to learn more about design and the role emotion plays in design, I can recommend the following books.

Cpp Standard Library

$
0
0

Introduction

There are far more things in the C++ Standard Library than we have time to cover. We will limit ourselves to looking at some of the most commonly used features that we haven’t yet explored.

Iterators

Iterators serve the same purpose as IEnumerable and related interfaces in .NET, such as providing a common way to navigate through collections. Given a std::vector, for example, you can loop through its collection of items using the following code:

	vector<int> vec;
	vec.push_back(1);
	vec.push_back(4);
	vec.push_back(7);
	vec.push_back(12);
	vec.push_back(8);
	for (auto i = begin(vec); i != end(vec); i++)
	{
		wcout << *i << endl;
	}

The std::begin function provides an iterator pointing to the first item of the collection. std::end provides an iterator that signals we have reached the end of a collection; the last item of the collection, assuming the collection has any items, is one item before the item we are given by std::end. That’s why we check for != in the for loop. If no items are in the collection, then std::begin and std::end will return the same value.

In addition to the iterators from those two template functions, many collections provide const iterators via member functions named cbegin and cend, reverse iterators (that loop through a collection backwards) via rbegin and rend, and const reverse iterators via crbegin and crend. In the previous example, you can replace begin(vec) with vec.rbegin() and end(vec) with vec.rend() to go through the vector in reverse.


Range-Based for Loops

C++11 has added an additional type of for loop, called the range-based for loop, which provides functionality similar to the foreach loop in C#. The range-based for loop uses iterators and saves you the trouble of de-referencing pointers and the possibility of improperly checking for the end. The range-based for loop equivalent to the for loop in the previous example looks like this:

	for (auto item : vec)
	{
		wcout << item << endl;
	}

std::vector and Other Containers

The collection you are likely to use most is std::vector. It is a fast, general-purpose collection similar to List<T> in .NET. It is found in the <vector> header file.

To add an item to the end of a vector, use the member function push_back. To remove an item from the end of a vector, use pop_back. You can access items at their index using [] the same way you would an array. To add an element or range of elements at a specific zero-based index, use the insert member function. To remove an element or range of elements at a specific zero-based index, use the erase member function.

A neat feature added in C++11 is the in-place construction functionality provided by the emplace and emplace_back member functions. Rather than constructing an object and then using insert or push_back to add it to the vector, you can call emplace_back and simply pass it the same arguments you would pass to the constructor for the type that the vector is holding. The vector will then construct and add a new instance of the object without the extra calculations that come with a copy or a move, and without using extra local memory.

The emplace function works the same, except you start by passing it an iterator that specifies the location. You can use cbegin() or cend() to add items to the beginning or end of the vector. If you have a specific zero-based index you want to emplace an item at, you can use vec.cbegin() + idx. You can also subtract from cend() if you want to place an item some number of spaces from the end.

vector offers more functionality, so you should definitely explore it further. The at member function will give you an item at an index, for example. There are ways to tell the vector to resize its internal capacity so you have more room free—if you knew you would need exactly 125 items, for instance—or so you minimize memory usage—if you added all the elements it will ever need and memory constraints are tight.

In addition to std::vector, several similar containers have different use cases. std::vector itself is the best choice when you need extremely fast, random access—when you will mostly be adding items to and removing items from the very end of the collection. If you also need to add items frequently to the front of the collection, you should consider using std::deque instead.

Use std::queue for a first-in, first-out container. Use std::stack for a last-in, first-out container.

The std::map class provides a sorted dictionary. std::unordered_map provides a hash table.

The std::set class is a sorted, keyed collection where the item stored is its own key, so each element must be unique. std::unordered_set is the unsorted equivalent of std::set.

The std::list class provides a doubly linked list. std::forward_list provides a singly linked list.

The <algorithm> Header

The <algorithm> header contains many very useful functions: things such as find, sort, copy, and all their related methods. The best way to learn them is to experiment with them.

The C Run-Time Library (CRT)

Some functionality from the C Runtime Library can be useful. Generally, the best way to access the library is to include the relevant <c_____> header file, such as <cstdlib>.

Visual Studio and Cpp

$
0
0

IntelliSense

If you’re using almost any of the Visual Studio keyboard mappings, typing Ctrl+J will bring up IntelliSense. In Visual Studio 2012, IntelliSense should appear automatically in C++. In Visual Studio 2010 and earlier, you need to invoke it manually.


Code Snippets

Code snippets are a new feature for C++ in Visual Studio 2012. They did not exist in earlier versions. If you’ve never used them in any language, then in a C# project, start typing “for” to begin a for loop; once IntelliSense has chosen the for snippet, press the Tab key twice and watch as a for loop appears complete with automatic fields you can edit. Use the Tab key to switch between fields. When you’re done editing the fields, press Enter. The cursor will be transported within the loop body with the field edits you made appearing as normal text.

Code snippets are particularly nice for switch statements that switch on an enum, since they will automatically populate the switch statement with all of the enum’s members.


Including Libraries

In C++, it’s usually not enough to just include a header file. Normally you need to tell the linker to link against a library that implements the code declared in the header file. To do this, you need to edit the project’s properties, accessible in the Project menu as ProjectName Properties…

In the properties, under Configuration Properties > Linker > Input, one of the fields is Additional Dependencies. This is a semicolon-separated list of the .LIB files you need to link against. It should end with %(AdditionalDependencies) so that any additional libraries linked via MS Build will be added.

For a typical DirectX 11 Metro-style game, for example, you might see the following:

d2d1.lib; d3d11.lib; dxgi.lib; ole32.lib; windowscodecs.lib; dwrite.lib; xaudio2.lib; xinput.lib; mfcore.lib; mfplat.lib; mfreadwrite.lib; mfuuid.lib; %(AdditionalDependencies)

If you receive a linker error telling you it cannot find a definition of something you are using, find the function or class on MSDN; the documentation will tell you both the header file and the library file you need.

Generating Assembly Code Files

If you want to view a very close approximation of the assembly code that your code is compiled into, in your project’s properties, under Configuration Properties > C/C++ > Output Files, set the Assembler Output option to something other than No Listing.

I’d recommend either Assembly-Only Listing (/FA) or Assembly with Source Code (/FAs). Assembly-Only Listing sprinkles enough line-number comments that you can usually cross-reference with your source code files to see what C++ code corresponds with the assembly code. That can be helpful if you want one place to see everything rather than flipping back and forth between whatever you’ve opened the .ASM file in (I use Notepad++) and Visual Studio.

Note that the generated assembly uses MASM macros (find them on MSDN). If you don’t know what a particular assembly instruction means (e.g., LEA), you can search the internet for it or download the appropriate programming manual from Intel’s site (assuming x86/Itanium), AMD’s site (assuming x64) or ARM Holding’s site (assuming ARM). If you’ve never learned any assembly, I definitely recommend doing so (try creating a simple Windows Console app).

Understanding assembly gives you a better understanding of how computers really work internally. Combine that with the knowledge that computers are all hardwired to begin executing the same code every time they are powered on (traditionally the BIOS on PCs, though that is now being replaced by UEFI), and the mystery of how and why computers work quickly begins to fade.


Terrifying Build Errors

If you come across a build error that looks completely horrible, chances are it’s from the linker. You’ll see messages like this, for instance:

Error	2	error LNK2019: unresolved external symbol &quot;public: __thiscall SomeClass::SomeClass(wchar_t const *)&quot; (??0SomeClass@@QAE@PB_W@Z) referenced in function &quot;void __cdecl DoSomething(void)&quot; (?DoSomething@@YAXXZ)	D:\VS2010Proj\CppSandbox\CppSandbox\CppSandbox.obj	CppSandbox

All that’s saying is it cannot find a function you said it should be able to find. In this case, I added the inline keyword to a constructor function definition in the CPP file without remembering to relocate that definition to the header file. Any inline functions need to be in the header so the linker won’t hate you.

All those ??s and @@ands are just how C++ mangles names when it has compiled code into object files. Name mangling is internally consistent for the compiler in question, but the ISO/IEC standard doesn’t mandate any particular schema for name mangling. Different compilers can, and often will, mangle things differently.

Normally, if you see a horrifying build error message, chances are it’s from the linker, and it’s an unresolved symbol error. If it’s saying it can’t find something you wrote, then check to make sure your declaration in the header file matches the definition, usually in the code file but maybe in the header, or maybe you forgot to write it, or maybe you declared it inline but still have it in the code file.

An example of this is in the previous case: my SomeClass::SomeClass(wchar_t const *) constructor function (I always write const type not type const, so even that bit is reconstructed).

If it’s someone else’s function or other symbol, then chances are you didn’t tell the linker about the .LIB file that contains it.

In .NET, you just add a reference to an assembly to get both the declaration bits and the actual definition all in one. In C++, the declaration is the header file, while the definition code—excluding inline code, which needs to be in the header file too—is in a separate library. Search the MSDN library for the missing symbol and find the name of the library file you need to add.

C++ build errors can look pretty scary, especially when you receive a build error involving a template. Those can make you want to quit. But don’t. Never let the horrible error messages win. First, figure out if it’s coming from the compiler (it’ll have a C#### error number format) or the linker (LNK#### error number format).

If from the compiler, it usually means a syntax error. Check things like whether you forgot the #pragma once at the top of your header file. Another problem could be where you used something from the Standard Library (e.g., endl) but forgot to have a #using namespace std; or to prefix it with std:: (i.e. std::endl).

You can do either or both, but you must do at least one. Some things might be in a different namespace. In Visual Studio 2010, some functionality is in the stdext namespace, for example. The same goes for any namespaces in your own code.

If you aren’t having any luck on your own, go to MSDN and type the first part of the error message. You’ll probably find some helpful links to discussions on the MSDN forums, on StackOverflow, perhaps an MSDN article or an MSDN blog post—maybe even just the error code’s page itself will have the hint you need. If all else fails, post a question on a forums site: MSDN, the appropriate StackExchange site, or App Hub.

A linker error is typically an unresolved symbol, which usually means you have a mismatch in declaration and definition, have an inline outside of its header, or don’t have the right library added to the project’s extra dependencies in the project’s linker options. If it’s something else, try the strategies from the previous paragraph; they apply just as well to linker errors as to compiler errors.

Networking with NSURLSession: Part 2

$
0
0

In the previous tutorial, I introduced you to NSURLSession. I talked about the advantages it has over NSURLConnection and how to use NSURLSession for simple tasks, such as fetching data from a web service and downloading an image from the web. In this tutorial, we’ll take a closer look at the configuration options of NSURLSession and how to cancel and resume a download task. We’ve got a lot of ground to cover so let’s get started.


Session Configuration

As we saw in the previous tutorial, a session, an instance of NSURLSession, is a configurable container for putting network requests into. The configuration of the session is handled by an instance of NSURLSessionConfiguration.

A session configuration object is nothing more than a dictionary of properties that defines how the session it is tied to behaves. A session has one session configuration object that dictates cookie, security, and cache policies, the maximum number of connections to a host, resource and network timeouts, etc. This is a significant improvement over NSURLConnection, which relied on a global configuration object with much less flexibility.

Mutability

Once a session is created and configured by a NSURLSessionConfiguration instance, the session’s configuration cannot be modified. If you need to modify a session’s configuration, you have to create a new session. Keep in mind that it is possible to copy a session’s configuration and modify it, but the changes have no effect on the session from which the configuration was copied.

Default Configuration

The NSURLSessionConfiguration class provides three factory constructors for instantiating standard configurations, defaultSessionConfiguration, ephemeralSessionConfiguration, and backgroundSessionConfiguration. The first method returns a copy of the default session configuration object, which results in a session that behaves similarly to an NSURLConnection object in its standard configuration. Altering a session configuration obtained through the defaultSessionConfiguration factory method doesn’t change the default session configuration which it’s a copy of.

Ephemeral Configuration

A session configuration object created by invoking the ephemeralSessionConfiguration factory method ensures that the resulting session uses no persistent storage for cookies, caches, or credentials. In other words, cookies, caches, and credentials are kept in memory. Ephemeral sessions are therefore ideal if you need to implement private browsing, something that simply wasn’t possible before the introduction of NSURLSession.

Background Configuration

The backgroundSessionConfiguration: factory method creates a session configuration object that enables out-of-process uploads and downloads. The upload and download tasks are managed by a background daemon and continue to run even if the application is suspended or crashes. We’ll talk more about background sessions later in this series.

Session Configuration

As we saw in the previous tutorial, creating a session configuration object is simple. In the example shown below, I used the defaultSessionConfiguration factory method to create a NSURLSessionConfiguration instance. Configuring a session configuration object is as simple as modifying its properties as shown in the example. We can then use the session configuration object to instantiate a session object. The session object serves as a factory for data, upload, and download tasks, with each task corresponding to a single request. In the example below, we query the iTunes Search API as we did in the previous tutorial.

// Create Session Configuration
NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];
// Configure Session Configuration
[sessionConfiguration setAllowsCellularAccess:YES];
[sessionConfiguration setHTTPAdditionalHeaders:@{ @"Accept" : @"application/json" }];
// Create Session
NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfiguration];
// Send Request
NSURL *url = [NSURL URLWithString:@"https://itunes.apple.com/search?term=apple&media=software"];
[[session dataTaskWithURL:url completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
    NSLog(@"%@", [NSJSONSerialization JSONObjectWithData:data options:0 error:nil]);
}] resume];

The example also illustrates how easy it is to add custom headers by setting the HTTPAdditionalHeaders property of the session configuration object. The beauty of the NSURLSession API is that every request that passes through the session is configured by the session’s configuration object. Adding authentication headers to a set of requests, for example, becomes easy as pie.


Canceling and Resuming Downloads

In the previous tutorial, I showed you how to download an image using the NSURLSession API. However, network connections are unreliable and it happens all too often that a download fails due to a flaky network connection. Fortunately, resuming a download isn’t difficult with the NSURLSession API. In the next example, I’ll show you how to cancel and resume the download of an image.

Before we take a closer look at resuming a download task, it is important to understand the difference between canceling and suspending a download task. It is possible to suspend a download task and resume it at a later time. Canceling a download task, however, stops the task and it isn’t possible to resume it at a later time. There is one alternative, though. It is possible to cancel a download task by calling cancelByProducingResumeData: on it. It accepts a completion handler that accepts one parameter, an NSData object that is used to resume the download at a later time by invoking downloadTaskWithResumeData: or downloadTaskWithResumeData:completionHandler: on a session object. The NSData object contains the necessary information to resume the download task where it left off.

Step 1: Outlets and Actions

Open the project we created in the previous tutorial or download it here. We start by adding two buttons to the user interface, one to cancel the download and one to resume the download. In the view controller’s header file, create an outlet and an action for each button as shown below.

#import <UIKit/UIKit.h>
@interface MTViewController : UIViewController
@property (weak, nonatomic) IBOutlet UIButton *cancelButton;
@property (weak, nonatomic) IBOutlet UIButton *resumeButton;
@property (weak, nonatomic) IBOutlet UIImageView *imageView;
@property (weak, nonatomic) IBOutlet UIProgressView *progressView;
- (IBAction)cancel:(id)sender;
- (IBAction)resume:(id)sender;
@end

Step 2: User Interface

Open the project’s main storyboard and add two buttons to the view controller’s view. Position the buttons as shown in the screenshot below and connect each button with its corresponding outlet and action.

Update the user interface.

Step 3: Refactoring

We’ll need to do some refactoring to make everything work correctly. Open MTViewController.m and declare one instance variable and two properties. The instance variable, session, will keep a reference to the session we’ll use for downloading the image.

#import "MTViewController.h"
@interface MTViewController () <NSURLSessionDelegate, NSURLSessionDownloadDelegate> {
    NSURLSession *_session;
}
@property (strong, nonatomic) NSURLSessionDownloadTask *downloadTask;
@property (strong, nonatomic) NSData *resumeData;
@end

We also need to refactor the viewDidLoad method, but first I’d like to implement a getter method for the session. Its implementation is pretty straightforward as you can see below. We create a session configuration object using the defaultSessionConfiguration factory method and instantiate the session object with it. The view controller serves as the session’s delegate.

- (NSURLSession *)session {
    if (!_session) {
        // Create Session Configuration
        NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];
        // Create Session
        _session = [NSURLSession sessionWithConfiguration:sessionConfiguration delegate:self delegateQueue:nil];
    }
    return _session;
}

With the session accessor implemented, the viewDidLoad method becomes much simpler. We create a download task, as we did in the previous tutorial, and store a reference to the task in downloadTask. We then tell the download task to resume.

- (void)viewDidLoad {
    [super viewDidLoad];
    // Create Download Task
    self.downloadTask = [self.session downloadTaskWithURL:[NSURL URLWithString:@"http://cdn.tutsplus.com/mobile/uploads/2014/01/5a3f1-sample.jpg"]];
    // Resume Download Task
    [self.downloadTask resume];
}

Step 4: Canceling the Download

The cancel: action contains the logic for canceling the download task we just created. If downloadTask is not nil, we call cancelByProducingResumeData: on the task. This method accepts one parameter, a completion block. The completion block also takes one parameter, an instance of NSData. If resumeData is not nil, we store a reference to the data object in view controller’s resumeData property.

If a download is not resumable, the completion block’s resumeData parameter is nil. Not every download is resumable so it’s important to check if resumeData is a valid NSData object.

- (IBAction)cancel:(id)sender {
    if (!self.downloadTask) return;
    // Hide Cancel Button
    [self.cancelButton setHidden:YES];
    [self.downloadTask cancelByProducingResumeData:^(NSData *resumeData) {
        if (!resumeData) return;
        [self setResumeData:resumeData];
        [self setDownloadTask:nil];
    }];
}

Step 5: Resuming the Download

Resuming the download task after it was canceled is easy. In the resume: action, we check if the view controller’s resumeData property is set. If resumeData is a valid NSData object, we tell the session object to create a new download task and pass it the NSData object. This is all the session object needs to recreate the download task that we canceled in the cancel: action. We then tell the download task to resume and set resumeData to nil.

- (IBAction)resume:(id)sender {
    if (!self.resumeData) return;
    // Hide Resume Button
    [self.resumeButton setHidden:YES];
    // Create Download Task
    self.downloadTask = [self.session downloadTaskWithResumeData:self.resumeData];
    // Resume Download Task
    [self.downloadTask resume];
    // Cleanup
    [self setResumeData:nil];
}

Build the project and run the application in the iOS Simulator or on a physical device. The download should start automatically. Tap the cancel button to cancel the download and tap the resume button to resume the download.

Step 6: Finishing Touches

There are a number of details we need to take care of. First of all, the buttons shouldn’t always be visible. We’ll use key value observing to show and hide the buttons when necessary. In viewDidLoad, hide the buttons and add the view controller as an observer of itself for the resumeData and downloadTask key paths.

- (void)viewDidLoad {
    [super viewDidLoad];
    // Add Observer
    [self addObserver:self forKeyPath:@"resumeData" options:NSKeyValueObservingOptionNew context:NULL];
    [self addObserver:self forKeyPath:@"downloadTask" options:NSKeyValueObservingOptionNew context:NULL];
    // Setup User Interface
    [self.cancelButton setHidden:YES];
    [self.resumeButton setHidden:YES];
    // Create Download Task
    self.downloadTask = [self.session downloadTaskWithURL:[NSURL URLWithString:@"http://cdn.tutsplus.com/mobile/uploads/2014/01/5a3f1-sample.jpg"]];
    // Resume Download Task
    [self.downloadTask resume];
}

In observeValueForKeyPath:ofObject:change:context:, we hide the cancel button if resumeData is nil and we hide the resume button if downloadTask is nil. Build the project and run the application one more time to see the result. This is better. Right?

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
    if ([keyPath isEqualToString:@"resumeData"]) {
        [self.resumeButton setHidden:(self.resumeData == nil)];
    } else if ([keyPath isEqualToString:@"downloadTask"]) {
        [self.cancelButton setHidden:(self.downloadTask == nil)];
    }
}

Step 7: Invalidating the Session

There is one key aspect of NSURLSession that I haven’t talked about yet, session invalidation. The session keeps a strong reference to its delegate, which means that the delegate isn’t released as long as the session is active. To break this reference cycle, the session needs to be invalidated. When a session is invalidated, active tasks are canceled or finished, and the delegate is sent a URLSession:didBecomeInvalidWithError: message and the session releases its delegate.

There are several places that we can invalidate the session. Since the view controller downloads only one image, the session can be invalidated when the download finishes. Take a look at the updated implementation of URLSession:downloadTask:didFinishDownloadingToURL:. The cancel button is also hidden when the download finishes.

- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location {
    NSData *data = [NSData dataWithContentsOfURL:location];
    dispatch_async(dispatch_get_main_queue(), ^{
        [self.cancelButton setHidden:YES];
        [self.progressView setHidden:YES];
        [self.imageView setImage:[UIImage imageWithData:data]];
    });
    // Invalidate Session
    [session finishTasksAndInvalidate];
}

Conclusion

The example project we created in this tutorial is a simplified implementation of how to cancel and resume downloads. In your applications, it may be necessary to write the resumeData object to disk for later use and it may be possible that several download tasks are running at the same time. Even though this adds complexity, the basic principles remain the same. Be sure to prevent memory leaks by always invalidating a session that you no longer need.

Introducing the New Mobile Development Editor: Bart Jacobs

$
0
0

We’re excited to announce a few changes to the Tuts+ team this week. After working as mobile editor for over three and a half years, we’re saying goodbye to Mark Hammonds, and offering a warm welcome to Bart Jacobs!


Thanks to Mark Hammonds

Everyone at Tuts+ would like to thank Mark for everything he has brought to the team over the years and the incredible work he has done here for mobile development education. He has been here since the very beginning, but felt it was the right time to focus fully on his own mobile and web app development projects over at Bitmotive. We wish him well with everything he’s moving on to!


Welcome to Bart Jacobs

bart

We are incredibly excited to officially introduce Bart Jacobs as our new Mobile Development Editor. Bart runs Code Foundry, a mobile and web development company based in Belgium. His primary area of expertise is iOS development, but he’s also skilled in Web, JavaScript, Ruby, and Cocoa development, and an avid fan of film music and coffee—a winning combination! You can follow Bart on Twitter and read his tutorials on Tuts+.


The Future & Your Suggestions

We’re extremely excited to have Bart on board to take mobile development on Tuts+ into the future. There are lots of exciting new developments coming up in the next few months and Bart is the perfect person to make mobile development education even better. Be sure to give him a warm welcome!

We’d also love to take this opportunity to ask for your suggestions and ideas for the mobile development topics you’d like to see covered over the next few months. Let us know what you’d like to see, and how we can best serve your development education needs.

Corona SDK: Create a Helicopter Obstacles Game

$
0
0

In this tutorial, I’ll be showing you how to create an obstacles avoiding game using the Corona SDK. You’ll learn more about touch controls, collision detection, and physics. The objective of the game is to avoid as many obstacles as you can to obtain the highest score. Let’s get started.


1. Application Overview

App Overview

Using ready-made graphics, we’ll create an entertaining game using the Lua programming language and the Corona SDK APIs. The player will be able to move a helicopter on the screen and needs to avoid any obstacles it comes across. You can modify the parameters in the code to customize the game.


2. Target Device

Target Device

The first thing we have to do is select the platform we want to run our application on so we’re able to choose the size for the images we’ll use.

The iOS platform has the following requirements:

  • iPad 1/2/Mini: 1024px x 768px, 132 ppi
  • iPad Retina: 2048px x 1536px, 264 ppi
  • iPhone/iPod Touch: 320px x 480px, 163 ppi
  • iPhone/iPod Retina: 960px x 640px, 326 ppi
  • iPhone 5/iPod Touch: 1136px x 640px, 326 ppi

Because Android is an open platform, there are many different devices and resolutions. A few of the more common screen characteristics are:

  • Asus Nexus 7 Tablet: 800px x 1280px, 216 ppi
  • Motorola Droid X: 854px x 480px, 228 ppi
  • Samsung Galaxy SIII: 720px x 1280px, 306 ppi

In this tutorial, we’ll be focusing on the iOS platform in terms of graphics. In particular, we’ll be developing for the iPhone and iPod Touch. However, the code of this tutorial can also be used in you target the Android platform.


3. Interface

Interface

We’ll use a simple user interface involving multiple shapes, buttons, bitmaps, and more. The graphics that we’ll use for this tutorial can be found in the project included with this tutorial.


4. Export Graphics

Export Graphics

Depending on the device you’ve selected, you may need to convert the graphics to the recommended resolution (ppi), which you can do in your favorite image editor. I used the Adjust Size… option in the Tools menu in the Preview application on OS X. Remember to give the images a descriptive name and save them in your project folder.


5. Application Configuration

We’ll use a configuration file, config.lua, to make the application go full screen across devices. The configuration file shows the original screen size and the method used to scale the content in case the application is run on a different resolution.

application =
{
    content =
    {
        width = 320,
        height = 480,
        scale = "letterbox"
    },
}

6.main.lua

Let’s write the actual application. Open your preferred Lua editor. Any plain text editor will work, but it is recommended to use a text editor that has syntax highlighting. Create a new file and save it as main.lua in your project folder.


7. Code Structure

We’ll structure our code as if it were a class. If you’re familiar with ActionScript or Java, you should find the project structure familiar.

Necesary Classes
Variables and Constants
Declare Functions
    contructor (Main function)
    class methods (other functions)
call Main function

8. Hide Status Bar

display.setStatusBar(display.HiddenStatusBar)

This code snippet hides the status bar. The status bar is the bar at the top of the device’s screen that shows the time, signal, and other indicators.


9. Import Physics

We’ll use the physics library to handle collisions. Import the library using the code snippet shown below.

-- Physics
local physics = require('physics')
physics.start()

10. Background

Background

A simple background for the application’s user interface. The code snippet below draws the background to the screen.

-- Graphics
-- [Background]
local gameBg = display.newImage('gameBg.png')

11. Title View

Title View

This is the title view. It’s the first interactive screen to appear in our game. These variables store its components.

-- [Title View]
local title
local playBtn
local creditsBtn
local titleView

12. Credits View

Credits View

The credits view shows the credits and copyright of the application. This variable is used to store it.

-- [CreditsView]
local creditsView

13. Instructions Message

Instructions

A message with instructions will appear at the start of the game and it will disappear after the first tap.

-- Instructions
local ins

14. Helicopter

Helicopter

This is the helicopter graphic. The player will control the helicopter using touch controls.

-- Helicopter
local helicopter

15. Blocks

Blocks

The blocks are the obstacles the player needs to avoid.

-- Blocks
local blocks = {}

16. Alert

Alert

The alert is displayed when the player misses the ball and the game is over. It displays a message and ends the game.

-- Alert
local alertView

17. Sounds

Sounds

To liven up the game, we’ll use sound effects. The sounds used in the game were obtained from as3soundfxr. I found the background music on playonloop.

-- Sounds
local bgMusic = audio.loadStream('POL-rocket-station-short.wav')
local explo = audio.loadSound('explo.wav')

18. Variables

The following code snippet shows the variables that we’ll use. Read the comments to understand what each variable is used for.

-- Variables
local timerSrc --Blocks timer
local yPos = {90, 140, 180} --Possible positions for the blocks
local speed = 5 --Block speed
local speedTimer --Increases blocks speed
local up = false --Used to determine if helicopter is going up
local impulse = -60 --physics value to make helicopter go up

19. Declare Functions

Declare all functions as local at the start.

-- Functions
local Main = {}
local startButtonListeners = {}
local showCredits = {}
local hideCredits = {}
local showGameView = {}
local gameListeners = {}
local createBlock = {}
local movePlayer = {}
local increaseSpeed = {}
local update = {}
local alert = {}

20. Constructor

Next, we create the function that will initialize the game logic.

function Main()
  -- code...
end

21. Add Title View

We start by placing the title view in the stage and call a function that will add tap listeners to the buttons.

function Main()
  titleBg = display.newImage('titleBg.png')
  playBtn = display.newImage('playBtn.png', 220, 178)
  creditsBtn = display.newImage('creditsBtn.png', 204, 240)
  titleView = display.newGroup(titleBg, playBtn, creditsBtn)
  startButtonListeners('add')
end

22. Start Button Listeners

The following function adds the necessary listeners to the TitleView‘s buttons.

function startButtonListeners(action)
  if(action == 'add') then
    playBtn:addEventListener('tap', showGameView)
    creditsBtn:addEventListener('tap', showCredits)
  else
    playBtn:removeEventListener('tap', showGameView)
    creditsBtn:removeEventListener('tap', showCredits)
  end
end

23. Show Credits

The credits screen is shown when the user taps the about button. A tap listener is added to the credits view to dismiss it when the user taps it.

function showCredits:tap(e)
  playBtn.isVisible = false
  creditsBtn.isVisible = false
  creditsView = display.newImage('credits.png', -110, display.contentHeight-80)
  transition.to(creditsView, {time = 300, x = 55, onComplete = function() creditsView:addEventListener('tap', hideCredits) end})
end

24. Hide Credits

When the user taps the credits view, it is animated out of the stage and remove.

function hideCredits:tap(e)
  playBtn.isVisible = true
  creditsBtn.isVisible = true
  transition.to(creditsView, {time = 300, y = display.contentHeight+creditsView.height, onComplete = function() creditsView:removeEventListener('tap', hideCredits) display.remove(creditsView) creditsView = nil end})
end

25. Show Game View

When the play button is tapped, the title view is animated off the screen and the game is revealed. There are a number of moving parts so we’ll take a closer look at each of them.

function showGameView:tap(e)
  transition.to(titleView, {time = 300, x = -titleView.height, onComplete = function() startButtonListeners('rmv') display.remove(titleView) titleView = nil end})

26. Instructions Message

The following code snippet adds the instructions message.

ins = display.newImage('ins.png', 180, 270)
  transition.from(ins, {time = 200, alpha = 0.1, onComplete = function() timer.performWithDelay(2000, function() transition.to(ins, {time = 200, alpha = 0.1, onComplete = function() display.remove(ins) ins = nil end}) end) end})

27. Score TextField

The following code snippet creates a text field that shows the player’s current score in the top-right of the stage.

-- TextFields
  scoreTF = display.newText('0', 450, 5, 'Marker Felt', 14)
  scoreTF:setTextColor(255, 255, 255)

28. Helicopter

Next, it is time to add the helicopter graphic to the stage as shown below.

-- Helicopter
  helicopter = display.newImage('helicopter.png', 23, 152)

29. Walls

In the following code snippet, we use the Corona graphics API to create several lines that we’ll add to the physics simulation a bit later in this tutorial. They will be used to detect collisions with the helicopter.

-- Walls
  local top = display.newRect(0, 60, 480, 1)
  top:setFillColor(34, 34, 34)
  local bottom = display.newRect(0, 260, 480, 1)
  bottom:setFillColor(34, 34, 34)
end

30. Physics

Next, we need to add the necessary physics to each object.

-- Add physics
  physics.addBody(helicopter)
  physics.addBody(top, 'static')
  physics.addBody(bottom, 'static')

31. Start Game

We create a group for the blocks, invoke the gameListeners function, and start the background music.

  blocks = display.newGroup()
  gameListeners('add')
  audio.play(bgMusic, {loops = -1, channel = 1})
end

32. Game Listeners

The following code snippet may seem complex, but it simply adds a few listeners to start the game logic.

function gameListeners(action)
  if(action == 'add') then
    gameBg:addEventListener('touch', movePlayer)
    Runtime:addEventListener('enterFrame', update)
    timerSrc = timer.performWithDelay(1300, createBlock, 0)
    speedTimer = timer.performWithDelay(5000, increaseSpeed, 5)
    helicopter:addEventListener('collision', onCollision)
  else
    gameBg:addEventListener('touch', movePlayer)
    Runtime:removeEventListener('enterFrame', update)
    timer.cancel(timerSrc)
    timerSrc = nil
    timer.cancel(speedTimer)
    speedTimer = nil
    helicopter:removeEventListener('collision', onCollision)
  end
end

33. Create a Block

As its name indicates, the createBlock function creates a block and draws it to the screen. The resulting object is added to the physics engine to check for collisions.

function createBlock()
  local b
  local rnd = math.floor(math.random() * 4) + 1
  b = display.newImage('block.png', display.contentWidth, yPos[math.floor(math.random() * 3)+1])
  b.name = 'block'
  -- Block physics
  physics.addBody(b, 'kinematic')
  b.isSensor = true
  blocks:insert(b)
end

34. Move Function

In the movePlayer function, we update the up variable. As long as its value is equal to true, the update function moves the helicopter up.

function movePlayer(e)
  if(e.phase == 'began') then
    up = true
  end
  if(e.phase == 'ended') then
    up = false
    impulse = -60
  end
end

35. Increase Speed

To make the game more interesting, a timer increases the speed every five seconds. An icon is displayed to alert the player of change in speed.

function increaseSpeed()
  speed = speed + 2
  -- Icon
  local icon = display.newImage('speed.png', 204, 124)
  transition.from(icon, {time = 200, alpha = 0.1, onComplete = function() timer.performWithDelay(500, function() transition.to(icon, {time = 200, alpha = 0.1, onComplete = function() display.remove(icon) icon = nil end}) end) end})
end

36. Move Helicopter

The update function checks the value of up and moves the helicopter up if it is equal to true.

function update(e)
  -- Move helicopter up
  if(up) then
    impulse = impulse - 3
    helicopter:setLinearVelocity(0, impulse)
  end

37. Move Blocks

Next, it is time to move the blocks. We use the speed variable to determine how many pixels the blocks should be moved every frame.

-- Move Blocks
  if(blocks ~= nil)then
    for i = 1, blocks.numChildren do
      blocks[i].x = blocks[i].x - speed
    end
  end

38. Update Score

The algorithm to update the score is simple. The score is incremented by one every frame for as long as the helicopter hasn’t crashed. Simple. Right?

  -- Score
  scoreTF.text = tostring(tonumber(scoreTF.text) + 1)
end

39. Collisions

The onCollision function verifies if the helicopter has collided with a block. If a collision was detected, we play a sound effect, an explosion, remove the graphics, and show an alert to the player.

function onCollision(e)
  audio.play(explo)
  display.remove(helicopter)
  alert()
end

40. Alert

The alert function creates an alert view and shows it to the user. The game then ends.

function alert()
  gameListeners('rmv')
  alert = display.newImage('alert.png', (display.contentWidth * 0.5) - 105, (display.contentHeight * 0.5) - 55)
  transition.from(alert, {time = 300, xScale = 0.5, yScale = 0.5})
end

41. Invoke Main Function

In order to start the game, the Main function needs to be invoked. With the rest of the code in place, we do that here.

Main()

42. Loading Screen

Loading Screen

On the iOS platform, the file named Default.png is displayed while the application is launching. Add this image to your project’s source folder, it will be automatically added by the Corona compiler.


43. Icon

Icon

Using the graphics you created earlier, you can now create a nice icon. The dimensions of the icon size for a non-retina iPhone are 57px x 57px, while the retina version needs to be 114px x 114px. The artwork for iTunes is required to be 1024px x 1024px. I suggest creating the iTunes artwork first and then creating the smaller sized images by scaling the iTunes artwork down to the correct dimensions. There is no need to make the application icon glossy or add rounded corners as this is taken care of by the operating system for you.


44. Testing in Simulator

Testing

It’s time to test our application in the simulator. Open the Corona Simulator, browse to your project folder, and click Open. If everything works as expected, you’re ready for the final step.


45. Build Project

Build

In the Corona Simulator, go to File > Build and select the target device. Fill out the required fields and click Build. Wait a few seconds and your application is ready to test on a device and/or to be submitted for distribution.


Conclusion

In this tutorial, we’ve learned about touch listeners, collision detection, physics as well as a few other skills that can be useful in a wide number of games. Experiment with the final result and try to modify the game to create your own version of the game. I hope you liked this tutorial and found it helpful. Thank you for reading.

Getting Started with Lua and the Corona SDK

$
0
0

In this tutorial, you will learn the basics of the Lua programming language and I will help you getting started with writing applications for iOS and Android. Excited? Let’s dive right in.


Introduction

In this tutorial, we will take a look at the Corona SDK and the Lua programming language. Even though Lua isn’t difficult to pick up, it is recommended to have some experience with other languages, such as JavaScript, PHP, Java, or Ruby. We will cover the very basics of the Corona SDK and Lua to get you familiar with developing for the Corona platform. You will see that it takes very little effort and code to get up and running. I’m ready when you are.


1. Introducing Lua and the Corona SDK

In the past, mobile developers faced a difficult predicament. Should they develop applications for iOS or Android? Most iOS developers use Objective-C, while Android developers use Java. Fortunately, we’ve got the Corona SDK and the Lua programming language, which enables cross platform mobile development. To put it simply, it means you can develop an application once and build it for iOS, Android, Kindle, and Nook.

The programming language we use when developing with the Corona SDK is Lua, which is moon in Portuguese. One of the main beneits of Lua, especially in combination with the Corona SDK, is that Lua is cross-platform as the language is written in C. Lua is not difficult to learn as you’ll find out in this tutorial. Lua was created in 1993 by a small group of people at the Pontifical Catholic University of Rio de Janeiro, Brazil. Lua is open source software so you can freely use it in your projects. It is distributed under the MIT license.

The Corona SDK is developed and maintained by Corona Labs and is a commercial platform. There are several pricing plans to choose from. There’s a free starter plan and paid plans starting from $19 per month.

For this tutorial, however, we’ll be using the starter plan. Even though you can develop Corona applications on several platforms, in this tutorial I’ll show you how to build applications using Windows and we’ll build for the Android platform.


2. Setting Up Lua and the Corona SDK

Are you ready to get started with cross platform mobile development? Visit the developer portal of the Corona SDK, create an account, and download the Corona SDK. As I mentioned, in this tutorial I’ll be using Windows, but you can follow along on OS X just as well. After the installation of the Corona SDK, open the Start menu and navigate to Corona SDK > Corona Simulator. You should see two windows as shown below.




3. Text Editors

Now that we have the Corona Simulator up and running, we need to get a text editor to write and edit Lua. I recommend Sublime Text 2, which is a free download. It’s a great and popular text editor that support syntax highlighting and a boatload of other useful features. This is especially useful if you’re writing large and complex applications. It supports Lua along with 43 other programming languages. Did I tell you Sublime Text if available on Windows, OS X as well as Linux? You can’t go wrong with Sublime Text 2.



4. Writing a Hello World Application

Head back to the Corona Simulator, hit New Project, and choose a directory to store your project’s files in. Select Blank as the project’s template, Phone Preset for Upright Screen Size, and Upright as the Default Orientation. Click OK to finalize the project setup and navigate to the directory where you created your new project. You should find three files, build.settings, config.lua, and main.lua. The only file we’ll need to edit is Main.lua. Open this file with your editor of choice and replace the file’s contents with the code snippet below.

print("Hello World!");

Save the changes by pressing Ctrl+S and open the Corona Simulator window. Wait a minute. Nothing happened. That’s perfectly normal. We need to check the other window that looks like command prompt. It should display Hello World! as shown below.


The reason why the text was only displayed in the Corona Terminal and not in the Corona Simulator is, because the print command is only used for the Lua programming language. It cannot be used to display the words on the screen of the Corona Simulator or a physical device. However, this basic print command will still be useful when we develop application, especially for debugging purposes.


5. Hello World – Take 2

We’re going to create another Hello World! application. However, this time, we’ll make it display the words in the Corona Simulator itself. Delete the contents of main.lua and replace it with the code snippet shown below.

display.newText("Hello World!", 0, 0, native.systemFont, 16);

You may have noticed that this snippet was a bit longer than the previous one. Let’s see what this piece of code does for us.

  • display is the object we’re talking to.
  • newText is the function that we use to display the text on the screen.
  • "Hello@ World!" is the text we want to display.
  • 0, 0 are the x and y coordinates respectively.
  • native.systemFont is the font we use for the text and 16 is the font’s size.

If you save the changes and relaunch the Corona Simulator, you should see the following.



6. Variables and Math

What if you wanted to store a number as a variable for later use? The following code snippet shows how variables are declared in Lua.

local num1 = 3 + 3;
  • local is the keyword for declaring a variable.
  • num1 is the name of the variable.

If we combine this with the previous code snippet, we get the following.

local num1 = 3 + 3;
display.newText(num1, 0, 0, native.systemFont, 32);

The Corona Simulator should now display the number 6, which is the result of adding 3 and 3. Let’s try another example using math. Using the following code snippet, the Corona Simulator should display the number 18.

local num1 = 3 + 3;
display.newText(num1 * 3, 0, 0, native.systemFont, 32);

As you can see, it is perfectly possible to perform mathematical operations on a variable. In the above code snippet, we multiplied num1 by 3 using * 3. I’m sure you’ve already figured out that the asterisk is the multiplication operator in Lua.

  • + for addition
  • - for subtraction and negative numbers
  • * for multiplication
  • / for division

7. Images

Displaying images isn’t difficult either. To display an image, you need to add the image to the directory where main.lua sits. It is fine to create a subdirectory to keep the project’s resources separated and organized. Let’s do that now. Create a new directory in your project folder and name it images. Use the images directory to store your project’s images. The image I’d like to use for this tutorial is logo1.png and I’ve placed it in the images directory we created a moment ago.

As you can see in the following code snippet, displaying an image is almost as easy as displaying text. I dare to say it’s even easier as you don’t need to specify a font.

local photo1 = display.newImage("images/logo1.png", 0, 0);


8. Status Bar

If you look closely at the previous screenshot, you’ll notice that there’s a status bar at the top of the screen displaying the carrier, battery life, etc. Have you ever noticed that sometimes, when you open an application, games in particular, the status bar automatically disappears? Hiding the status bar is as simple as adding one line of code to main.lua. It’s a simple as that. Update your project and take a look at the result in the Corona Simulator.

display.setStatusBar(display.HiddenStatusBar);

It is useful to know that the status bar can have different styles. The names of the styles speak for themselves. For many applications, especially games, using HiddenStatusBar is most suitable.

display.setStatusBar(display.DefaultStatusBar);
display.setStatusBar(display.DarkStatusBar);
display.setStatusBar(display.TranslucentStatusBar);


9. Rectangles, Borders, and Colors

Let’s move on with shapes. The first shape we’ll display is a rectangle. Let’s see what it takes to display a rectangle on the screen.

local rect1 = display.newRect(10, 20, 150, 50);
  • local rect1 declares a variable for the rectangle.
  • display.newRectcreates the rectangle shape.
  • (10, 20, 150, 50) define the x and y coordinates and the width and height, respectively.

Let’s add some color to the rectangle.

rect1:setFillColor(51, 255, 0);

Hmmm. What does this mean?

  • rect1 is the variable we declared earlier.
  • setFillColor is the method we use to fill the rectangle with a color.
  • (51, 255, 0) specify the red (51), green (255), and blue (0) value of the color we use.

Let’s expand this example with a border or stroke as shown in the following code snippet.

rect1.strokeWidth = 8;
rect1:setStrokeColor(80, 200, 130);
  • rect1.strokeWidth = 8 sets the strokeWidth property of the rectangle to 8.
  • rect1.setStrokeColor(80, 200, 130) sets the strokeColor property of the rectangle to the color specified by the values 80, 200, and 130 as we saw earlier.


10. Comments

Comments may seem trivial and even obsolete, but they are important and even more so when you work in a team. Comments are very useful for documenting code and this applies both for you as your colleagues. It improves the readability of code for other people in your team. In Lua, comments are easy to use. Take a look at the following example.

--this is a comment

Comments have no effect on your application in terms of how it works. They are only there for the developer. The following code snippet will not print Hello World! to the terminal.

--print("Hello World!")

You can also write comments that span several lines, which is useful if you need to explain how a particularly complex piece of code works or if you want to write an introduction to an application or project.

--[[
This is comment
spans
several lines.
]]

Conclusion

In this tutorial, you’ve learned the basics of Lua and the Corona SDK. We installed and set up the Corona SDK, downloaded and used a text editor for editing Lua, wrote several applications, and ran them in the Corona Simulator. We also learned how to use variables to store pieces of data, display images on the screen, configure the status bar, and draw shapes to the screen. And, last but not least, we saw how to use comments and why you should use comments in your code. I hope that this tutorial was helpful to you. Stay tuned for more.

If you’d like to learn more about the Corona SDK, I recommend visiting the Corona Labs developer website. It is filled with resources and guides to get you started. You can also explore the example applications that are included in the Corona SDK that you downloaded and installed earlier.

The Lua programming language also has its own website. It contains everything you need to know about the language, including a getting started guide and a very, very detailed manual. Make sure to visit the Lua website if you decide to continue with Corona development.


Working with NSURLSession: Part 3

$
0
0

In the previous tutorials, we explored the fundamentals of the NSURLSession API. There is one other feature of the NSURLSession API that we haven’t look into yet, that is, out-of-process uploads and downloads. In the next two tutorials, I will show you how to create a very simple podcast client that enables background downloads.


Introduction

The podcast client that we’re about to create isn’t really going to be that functional. It will allow the user to query the iTunes Search API for a list of podcasts, select a podcast, and download episodes. Since we are focusing on the NSURLSession API, we won’t go into playing the episodes the application downloads.

The project, however, will teach you how to use data tasks and download tasks in a real world application. The podcast client will also enable background downloads for which we’ll leverage NSURLSession‘s out-of-process API. We have quite a few things to do so let’s not waste time and get started.


1. Project Setup

Fire up Xcode 5, select New > Project… from the File menu, and choose the Single View Application template from the list of iOS application templates. Name the application Singlecast, set the Device Family to iPhone, and tell Xcode where you’d like to save the project. Hit Create to create the project.

Create the project in Xcode.

Configure the project in Xcode.

2. Update Storyboard

The first thing we need to do is edit the project’s main storyboard. Open Main.storyboard, select the storyboard’s only view controller, and choose Embed In > Navigation Controller from the Editor menu. The reason for embedding the view controller in a navigation controller will become clear later in this tutorial.

Embed the view controller in a navigation controller.

3. Search View Controller

Step 1: Create Class Files

As I mentioned in the introduction, to keep things simple, the user will only be able to subscribe to one podcast. Let’s start by creating the search view controller. Select New > File… from the File menu and choose Objective-C class from the options on the right. Name the class MTSearchViewController and make it a subclass of UIViewController. Leave the check box labeled With XIB for user interface unchecked. Tell Xcode where you want to save the class files and hit Create.

Create the files for the MTSearchViewController class.

Step 2: Update Class Interface

Before we create the user interface, open the view controller’s header file and update the class’s interface as shown below. We specify that the MTSearchViewController class conforms to the UITableViewDataSource, UITableViewDelegate, and UISearchBarDelegate protocols, we declare two outlets, searchBar and tableView as well as an action, cancel, to dismiss the search view controller.

#import <UIKit/UIKit.h>
@interface MTSearchViewController : UIViewController <UITableViewDataSource, UITableViewDelegate, UISearchBarDelegate>
@property (weak, nonatomic) IBOutlet UISearchBar *searchBar;
@property (weak, nonatomic) IBOutlet UITableView *tableView;
- (IBAction)cancel:(id)sender;
@end

Step 3: Create User Interface

Revisit the project’s main storyboard and drag a new view controller from the Object Library on the right. Select the new view controller, open the Identity Inspector on the right, and set the view controller’s class to MTSearchViewController. With the new view controller still selected, open the Editor menu and choose Embed In > Navigation Controller. Drag a table view to the view controller’s view and connect the table view’s dataSource and delegate outlets with the search view controller.

Add a table view to the search view controller's view and connect its dataSource and delegate outlets.

With the table view still selected, open the Attributes Inspector, and set the number of prototype cells to 1. Select the prototype cell and set its style property to Subtitle and its identifier to SearchCell.

Create and configure a prototype cell.

Drag a search bar from the Object Library and add it to the table view’s header view. Select the search bar and connect its delegate outlet with the view controller.

Add a search bar to the table view's header view and connect the delegate outlet.

Select the view controller and connect its searchBar and tableView outlets with the search bar and table view respectively. There are a few other things that we need to do before we’re done with the storyboard.

Open the Object Library and drag a bar button item to the navigation bar. Select the bar button item, connect it with the cancel: action we declared in the search view controller’s interface, and change its Identifier in the Attributes Inspector to Cancel.

Add a bar button item to the search view controller.

Drag a bar button item to the navigation bar of the view controller (not the search view controller) and change its Identifier in the Attributes Inspector to Add. Control drag from the bar button item to the search view controller’s navigation controller and select modal from the menu that pops up. This creates a segue from the view controller to the search view controller’s navigation controller.

If you were to control drag from the view controller’s bar button item directly to the search view controller instead of its navigation controller, the navigation controller would never be instantiated and you wouldn’t see a navigation bar at the top of the search view controller.

Create a segue from the view controller to the search view controller's navigation controller.

Step 4: Table View Implementation

Before we implement the UITableViewDataSource and UITableViewDelegate protocols in the MTSearchViewController class, we need to declare a property that stores the search results we’ll get back from the iTunes Search API. Name the property podcasts as shown below. We also declare a static string that will serve as a cell reuse identifier. It corresponds to the identifier we set on the prototype cell a few moments ago.

#import "MTSearchViewController.h"
@interface MTSearchViewController ()
@property (strong, nonatomic) NSMutableArray *podcasts;
@end
static NSString *SearchCell = @"SearchCell";

The implementation of numberOfSectionsInTableView: is as easy as it gets. We return 1 if self.podcasts is not nil and 0 if it is. The implementation of tableView:numberOfRowsInSection: is pretty similar as you can see below. In tableView:cellForRowAtIndexPath:, we ask the table view for a cell by passing the cell reuse identifier, which we declared earlier, and indexPath. We fetch the corresponding item from the podcasts data source and update the table view cell. Both tableView:canEditRowAtIndexPath: and tableView:canMoveRowAtIndexPath: return NO.

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return self.podcasts ? 1 : 0;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return self.podcasts ? self.podcasts.count : 0;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:SearchCell forIndexPath:indexPath];
    // Fetch Podcast
    NSDictionary *podcast = [self.podcasts objectAtIndex:indexPath.row];
    // Configure Table View Cell
    [cell.textLabel setText:[podcast objectForKey:@"collectionName"]];
    [cell.detailTextLabel setText:[podcast objectForKey:@"artistName"]];
    return cell;
}
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
    return NO;
}
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath {
    return NO;
}

Before running the application, implement the cancel: action in which we dismiss the search view controller.

- (IBAction)cancel:(id)sender {
    [self dismissViewControllerAnimated:YES completion:nil];
}

Build the project and run the application to make sure that the foundation is working as expected. It’s time to start using the NSURLSession API to query the iTunes Search API.

Step 5: Creating a Session

Let’s begin by declaring two additional private properties in the MTSearchViewController class, session and dataTask. The session variable is used to store a reference to the NSURLSession instance we’ll be using for querying Apple’s API. We also keep a reference to the data task that we will use for the request. This will enable us to cancel the data task if the user updates the search query before we’ve received a response from the API. If you have an eye for detail, you may have noticed that the MTSearchViewController class also conforms to the UIScrollViewDelegate protocol. The reason for this will become clear in a few minutes.

#import "MTSearchViewController.h"
@interface MTSearchViewController () <UIScrollViewDelegate>
@property (strong, nonatomic) NSURLSession *session;
@property (strong, nonatomic) NSURLSessionDataTask *dataTask;
@property (strong, nonatomic) NSMutableArray *podcasts;
@end

The session is created in its getter method as you can see below. Its implementation shouldn’t hold any surprises if you’ve read the previous tutorials. We override the getter method of the session property to lazily load the session and confine the session’s instantiation and configuration in its getter method. This makes for clean and elegant code.

- (NSURLSession *)session {
    if (!_session) {
        // Initialize Session Configuration
        NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];
        // Configure Session Configuration
        [sessionConfiguration setHTTPAdditionalHeaders:@{ @"Accept" : @"application/json" }];
        // Initialize Session
        _session = [NSURLSession sessionWithConfiguration:sessionConfiguration];
    }
    return _session;
}

Step 6: Searching

To respond to the user’s input in the search bar, we implement searchBar:textDidChange: of the UISearchBarDelegate protocol. The implementation is simple. If searchText is nil, the method returns early. If the length of searchText is less than four characters long, we reset the search by invoking resetSearch. If the query is four characters or longer, we perform a search by calling performSearch on the search view controller.

- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText {
    if (!searchText) return;
    if (searchText.length <= 3) {
        [self resetSearch];
    } else {
        [self performSearch];
    }
}

Before we inspect performSearch, let’s take a quick look at resetSearch. All that we do in resetSearch is clearing the contents of podcasts and reloading the table view.

- (void)resetSearch {
    // Update Data Source
    [self.podcasts removeAllObjects];
    // Update Table View
    [self.tableView reloadData];
}

The heavy lifting is done in performSearch. After storing the user’s input in a variable named query, we check if dataTask is set. If it is set, we call cancel on it. This is important as we don’t want to receive a response from an old request that may no longer be relevant to the user. This is also the reason why we have only one active data task at any one time. There is no advantage in sending multiple requests to the API.

Next, we ask the session for a new data task instance by passing it an NSURL instance and a completion handler. Remember that the session is the factory that creates tasks. You should never create tasks yourself. If we get a valid data task from the session, we call resume on it as we saw in the previous tutorials.

The logic inside the completion handler is interesting to say the least. The error object is important to us for several reasons. Not only will it tell us if something went wrong with the request, but it’s also useful for determining if the data task was canceled. If we do get an error object, we check whether its error code is equal to -999. This error code indicates the data task was canceled. If we get another error code, we log the error to the console. In a real application, you’d need to improve the error handling and notify the user when an error is thrown.

If no error was passed to the completion handler, we create a dictionary from the NSData instance that was passed to the completion handler and we extract the results from it. If we have an array of results to work with, we pass it to processResults:. Did you notice we invoked processResults: in a GCD (Grand Central Dispatch) block? Why did we do that? I hope you remember, because it’s a very important detail. We have no guarantee that the completion handler is invoked on the main thread. Since we need to update the table view on the main thread, we need to make sure that processResults: is called on the main thread.

- (void)performSearch {
    NSString *query = self.searchBar.text;
    if (self.dataTask) {
        [self.dataTask cancel];
    }
    self.dataTask = [self.session dataTaskWithURL:[self urlForQuery:query] completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
        if (error) {
            if (error.code != -999) {
                NSLog(@"%@", error);
            }
        } else {
            NSDictionary *result = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
            NSArray *results = [result objectForKey:@"results"];
            dispatch_async(dispatch_get_main_queue(), ^{
                if (results) {
                    [self processResults:results];
                }
            });
        }
    }];
    if (self.dataTask) {
        [self.dataTask resume];
    }
}

Before we look at the implementation of processResults:, I want to quickly show you what happens in urlForQuery:, the helper method we use in performSearch. In urlForQuery:, we replace any spaces with a + sign to ensure that the iTunes Search API is happy with what we send it. We then create an NSURL instance with it and return it.

- (NSURL *)urlForQuery:(NSString *)query {
    query = [query stringByReplacingOccurrencesOfString:@" " withString:@"+"];
    return [NSURL URLWithString:[NSString stringWithFormat:@"https://itunes.apple.com/search?media=podcast&entity=podcast&term=%@", query]];
}

In processResults:, the podcasts variable is cleared, populated with the contents of results, and the results are displayed in the table view.

- (void)processResults:(NSArray *)results {
    if (!self.podcasts) {
        self.podcasts = [NSMutableArray array];
    }
    // Update Data Source
    [self.podcasts removeAllObjects];
    [self.podcasts addObjectsFromArray:results];
    // Update Table View
    [self.tableView reloadData];
}

Step 6: Selecting a Podcast

When the user taps a row in the table view to select a podcast, tableView:didSelectRowAtIndexPath: of the UITableViewDelegate protocol is invoked. Its implementation may seem odd at first so let me explain what’s going on. We select the podcast that corresponds with the user’s selection, store it in the application’s user defaults database, and dismiss the search view controller. We don’t notify anyone about this? Why we do this will become clear once we continue implementing the MTViewController class.

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    [tableView deselectRowAtIndexPath:indexPath animated:YES];
    // Fetch Podcast
    NSDictionary *podcast = [self.podcasts objectAtIndex:indexPath.row];
    // Update User Defatuls
    NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
    [ud setObject:podcast forKey:@"MTPodcast"];
    [ud synchronize];
    // Dismiss View Controller
    [self dismissViewControllerAnimated:YES completion:nil];
}

Step 7: Finishing Touches

There are two details I want to talk about before returning to the MTViewController class. When the search view controller is presented to the user, it is clear that she wants to search for podcasts. It is therefore a good idea to immediately present the keyboard. We do this in viewDidAppear: as shown below.

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    // Show Keyboard
    [self.searchBar becomeFirstResponder];
}

The keyboard needs to hide the moment the user starts scrolling through the search results. To accomplish this, we implement scrollViewDidScroll: of the UIScrollViewDelegate protocol. This explains why MTSearchViewController conforms to the UIScrollViewDelegate protocol. Have a look at the implementation of scrollViewDidScroll: shown below.

- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
    if ([self.searchBar isFirstResponder]) {
        [self.searchBar resignFirstResponder];
    }
}
The UITableView class is a subclass of UIScrollView, which is the reason the above approach works.

4. Looping Back

As we saw earlier, we store the user’s selection in the application’s user defaults database. We need to update the MTViewController class to make use of the user’s selection in the search view controller. In the view controller’s viewDidLoad method, we load the podcast from the user defaults database and we add the view controller as an observer of the user defaults database for the key path MTPodcast so that the view controller is notified when the value for MTPodcast changes.

- (void)viewDidLoad {
    [super viewDidLoad];
    // Load Podcast
    [self loadPodcast];
    // Add Observer
    [[NSUserDefaults standardUserDefaults] addObserver:self forKeyPath:@"MTPodcast" options:NSKeyValueObservingOptionNew context:NULL];
}

All we do in loadPodcast is storing the value for MTPodcast from the user defaults database in the view controller’s podcast property. This value will be nil if the user defaults database doesn’t contain an entry for MTPodcast. The view controller will gracefully handle this for us. Remember that, in Objective-C, you can send messages to nil without all hell breaking loose. This has its disadvantages, but it certainly has its advantages to.

- (void)loadPodcast {
    NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
    self.podcast = [ud objectForKey:@"MTPodcast"];
}

This also means that we need to declare a property named podcast in the view controller’s implementation file.

#import "MTViewController.h"
@interface MTViewController ()
@property (strong, nonatomic) NSDictionary *podcast;
@end

Let’s also take a quick look at setPodcast: and updateView.

- (void)setPodcast:(NSDictionary *)podcast {
    if (_podcast != podcast) {
        _podcast = podcast;
        // Update View
        [self updateView];
    }
}
- (void)updateView {
    // Update View
    self.title = [self.podcast objectForKey:@"collectionName"];
}

When the value in the user defaults database changes for the key MTPodcast, the view controller can respond to this change in observeValueForKeyPath:ofObject:change:context:. That’s how key value observing works. All we do in this method is updating the value of the view controller’s podcast property.

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
    if ([keyPath isEqualToString:@"MTPodcast"]) {
        self.podcast = [object objectForKey:@"MTPodcast"];
    }
}

When working with key value observing, it is instrumental to be aware of memory management and retain cycles. In this case, it means that we need to remove the view controller as an observer when the view controller is deallocated.

- (void)dealloc {
    [[NSUserDefaults standardUserDefaults] removeObserver:self forKeyPath:@"MTPodcast"];
}

5. Fetching and Parsing the Feed

Step 1: Adding Dependencies

The response we get back from the iTunes Search API includes a feedUrl attribute for each podcast. We could manually fetch the feed and parse it. However, to save some time, we’ll make use of MWFeedParser, a popular library that can do this for us. You can manually download and include the library in your project, but I am going to opt for Cocoapods. I prefer Cocoapods for managing dependencies in iOS and OS X projects. You can read more about Cocoapods on its website or on Mobiletuts+.

I am going to assume the Cocoapods gem is installed on your system. You can find detailed instructions in this tutorial.

Quit Xcode, navigate to the root of your Xcode project, and create a file named Podfile. Open this file in your text editor of choice and add the following three lines of code. In the first line, we specify the platform and the deployment target, which is iOS 7 in this example. The next two lines each specify a dependency of our Xcode project. The first one is the MWFeedParser library and I’ve also included the popular SVProgressHUD library, which will come in handy a bit later.

platform :ios, '7'
pod 'MWFeedParser'
pod 'SVProgressHUD'

Open a Terminal window, navigate to the root of your Xcode project, and execute the command pod install. This should install the dependencies and create an Xcode workspace. When Cocoapods is finished installing the project’s dependencies, it tells you to use the workspace it created for you. This is important so don’t ignore this advice. In the root of your Xcode project, you will see that Cocoapods has indeed created an Xcode workspace for you. Double-click this file and you should be ready to go.

Install the project's dependencies using Cocoapods.

Step 2: Fetching and Parsing the Feed

Open the implementation file of the MTViewController class, add an import statement for MWFeedParser and SVProgressHUD, and declare two properties, episodes and feedParser. We also need to make MTViewController conform to the MWFeedParserDelegate protocol.

#import "MTViewController.h"
#import "MWFeedParser.h"
#import "SVProgressHUD.h"
@interface MTViewController () <MWFeedParserDelegate>
@property (strong, nonatomic) NSDictionary *podcast;
@property (strong, nonatomic) NSMutableArray *episodes;
@property (strong, nonatomic) MWFeedParser *feedParser;
@end

Next, we update setPodcast: by invoking fetchAndParseFeed, a helper method in which we use the MWFeedParser class to fetch and parse the podcast’s feed.

- (void)setPodcast:(NSDictionary *)podcast {
    if (_podcast != podcast) {
        _podcast = podcast;
        // Update View
        [self updateView];
        // Fetch and Parse Feed
        [self fetchAndParseFeed];
    }
}

In fetchAndParseFeed, we get rid of our current MWFeedParser instance if we have one and initialize a new instance with the podcast’s feed URL. We set the feedParseType property to ParseTypeFull and set the view controller as the feed parser’s delegate. Before we fetch the feed, we use SVProgressHUD to show a progress HUD to the user.

- (void)fetchAndParseFeed {
    if (!self.podcast) return;
    NSURL *url = [NSURL URLWithString:[self.podcast objectForKey:@"feedUrl"]];
    if (!url) return;
    if (self.feedParser) {
        [self.feedParser stopParsing];
        [self.feedParser setDelegate:nil];
        [self setFeedParser:nil];
    }
    // Clear Episodes
    if (self.episodes) {
        [self setEpisodes:nil];
    }
    // Initialize Feed Parser
    self.feedParser = [[MWFeedParser alloc] initWithFeedURL:url];
    // Configure Feed Parser
    [self.feedParser setFeedParseType:ParseTypeFull];
    [self.feedParser setDelegate:self];
    // Show Progress HUD
    [SVProgressHUD showWithMaskType:SVProgressHUDMaskTypeGradient];
    // Start Parsing
    [self.feedParser parse];
}

We also need to implement two methods of the MWFeedParserDelegate protocol, feedParser:didParseFeedItem: and feedParserDidFinish:. In feedParser:didParseFeedItem:, we initialize the episodes property if necessary and pass it the feed item that the feed parser hands to us.

- (void)feedParser:(MWFeedParser *)parser didParseFeedItem:(MWFeedItem *)item {
    if (!self.episodes) {
        self.episodes = [NSMutableArray array];
    }
    [self.episodes addObject:item];
}

In feedParserDidFinish:, we dismiss the progress HUD and update the table view. Did you say table view? That’s right. We need to add a table view and implement the necessary UITableViewDataSource protocol methods.

- (void)feedParserDidFinish:(MWFeedParser *)parser {
    // Dismiss Progress HUD
    [SVProgressHUD dismiss];
    // Update View
    [self.tableView reloadData];
}

Step 3: Displaying the Feed

Before we update the user interface, open MTViewController.h, declare an outlet for the table view, and tell the compiler the MTViewController class conforms to the UITableViewDataSource and UITableViewDelegate protocols.

#import <UIKit/UIKit.h>
@interface MTViewController : UIViewController <UITableViewDataSource, UITableViewDelegate>
@property (weak, nonatomic) IBOutlet UITableView *tableView;
@end

Open the main storyboard one more time and add a table view to the view controller’s view. Connect the table view’s dataSource and delegate outlets with the view controller and connect the view controller’s tableView outlet with the table view. Select the table view, open the Attributes Inspector, and set the number of prototype cells to 1. Select the prototype cell, set its style to Subtitle, and give it an identifier of EpisodeCell.

Adding a table view to the view controller.

Before we implement the UITableViewDataSource protocol, declare a static string named EpisodeCell in MTViewController.m. This corresponds with the identifier we set for the prototype cell in the storyboard.

static NSString *EpisodeCell = @"EpisodeCell";

Implementing the UITableViewDataSource protocol is simple as pie and very similar to how we implemented the protocol in the search view controller. The only difference is that the episodes variable contains instances of the MWFeedItem class instead of NSDictionary instances.

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return self.episodes ? 1 : 0;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return self.episodes ? self.episodes.count : 0;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:EpisodeCell forIndexPath:indexPath];
    // Fetch Feed Item
    MWFeedItem *feedItem = [self.episodes objectAtIndex:indexPath.row];
    // Configure Table View Cell
    [cell.textLabel setText:feedItem.title];
    [cell.detailTextLabel setText:[NSString stringWithFormat:@"%@", feedItem.date]];
    return cell;
}
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
    return NO;
}
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath {
    return NO;
}

Run the application in the iOS Simulator or on a physical device and run it through its paces. You should now be able to search for podcasts, select a podcast from the list, and see its episodes.


Conclusion

We’ve done a lot in this tutorial, but we still have quite a bit of work in front of us. In the next tutorial, we zoom in on downloading episodes from the feed and we’ll discuss background or out-of-process downloads. I will also show you how you can leverage another neat iOS 7 API to add the ability to download new episodes even when your application isn’t running. Stay tuned.

Consuming Web Services with kSOAP

$
0
0

In this tutorial, you’ll learn how to consume web services using the popular kSOAP library in an Android application. kSOAP is a reputable library loved by developers who have the need to parse WSDL (Web Service Definition Language) and SOAP (Simple Object Access Protocol) messages.


Introduction

The kSOAP library is an elegant, lightweight, and efficient SOAP client library. The library is open source, easy to use, and it can save you from the hassle of coding a custom parser. It is one of the more trusted SOAP libraries currently available and it’s frequently updated, which is a good sign for any open source project.

It is often risky to integrate open source software (OSS) in a project as it can cause unforeseen problems down the road. Always look for comments and reviews of other developers who have used the library. If the project isn’t under active development, it may be better to look for an alternative solution.

The objective of this tutorial is to make you familiar with the kSOAP library. For demonstration purposes, we’ll be using a simple web service from W3Schools. The web service is a Fahrenheit to Celsius converter. The web service accepts a value in degrees Fahrenheit and responds with the equivalent value in degrees Celsius. We’ll go through the example step by step. At the end of this tutorial, we’ll display the result on the user’s device.


1. Getting Started

Step 1: Project Setup

Start a new Android project and configure it as you please. Feel free to use your favorite IDE, but for this tutorial I’ll be using IntelliJ IDEA.

In the project’s manifest file, you need to specify that the application is allowed to connect to the internet. We’re also going to specify the target SDK version as well as the minimum SDK version. Take a look at the manifest file shown below.

<uses-sdk android:minSdkVersion="7" android:targetSdkVersion="17"/><uses-permission android:name="android.permission.INTERNET"/>

Step 2: Downloading kSOAP

Always try and use the latest stable release of a library or upgrade the library you’re using in an application after a major update has been released. It’s good practice to keep a project’s dependencies up to date for various reasons, such as security and bug fixes. In this tutorial, we’ll be using version 3.1.1 of the kSOAP library, which you can find on the project’s download page. After downloading the kSOAP library, add it to your project’s libs folder.

Step 3: Adding kSOAP to Your Project

In order to use the kSOAP library in your project, you’ll need to add it to your project. I’ll show you how to add it using IntelliJ IDEA. The steps might be slightly different if you’re using a different IDE, but the idea is the same. In IntelliJ IDEA, choose Project Structure… from the File menu, open the Modules pane, click the plus button at the bottom of the right pane, and select library. Navigate to the libs folder and select the kSOAP library. Take a look at the two images below for clarification.



The kSOAP library should now be visible as a dependency of your project. Click the check box next to the kSOAP library to add it to your project. Now that we’ve added the library to our project, it is time to put it to use. If you’re using IntelliJ IDEA, your project should look similar to the one shown below.



2.W3Schools Web Service

Using the kSOAP library to consume a web service involves a number of steps. However, before we dive head first into using the kSOAP library, it is useful to tell you a bit more about the web service we’ll be using.

Visit the website of the W3Schools web service that we’ll use in this tutorial. You’ll see that there are two operations, CelsiusToFahrenheit and FahrenheitToCelsius. The name of each operation is self-explanatory. The web service’s URL is the base URL that we’ll use to connect to the web service.

If you select an operation on the W3Schools website, you’re shown an example of the request that the web service expects as well as the response of the web service. Take a look at the code snippet below, which is an example request that the web service expects. Pay close attention to the SOAPAction in the code snippet. We will use it a bit later in this tutorial.

POST /webservices/tempconvert.asmx HTTP/1.1
Host: www.w3schools.com
Content-Type: text/xml; charset=utf-8
Content-Length: length
SOAPAction: "http://www.w3schools.com/webservices/FahrenheitToCelsius"<!--?xml version="1.0" encoding="utf-8"?-->
string

The next code snippet shows an example response of the web service.

HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: length<!--?xml version="1.0" encoding="utf-8"?-->
string

3. Using kSOAP

Step 1: Creating an Envelope

The first thing we need to do is creating a SOAP envelope using the SoapSerializationEnvelope class (org.ksoap2.serialization.SoapSerializationEnvelope), which you need to import from the kSOAP library. Take a look at the code snippet below, in which I have initialized an instance of the SoapSerializationEnvelope class.

SoapSerializationEnvelope envelope = getSoapSerializationEnvelope(request);

The getSoapSerializationEnvelope method isn’t defined in the kSOAP library. It’s a helper method that I’ve created that to make working with the kSOAP library a bit easier. The method returns the SOAP envelope that we need for the rest of the example. Take a look at the implementation of getSoapSerializationEnvelope below.

private final SoapSerializationEnvelope getSoapSerializationEnvelope(SoapObject request) {
    SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
    envelope.dotNet = true;
    envelope.implicitTypes = true;
    envelope.setAddAdornments(false);
    envelope.setOutputSoapObject(request);
    return envelope;
}

The getSoapSerializationEnvelope method accepts a SoapObject instance, which is the request. We’ll see how to create the request in just a few minutes. When creating an instance of the SoapSerializationEnvelope class, the SoapEnvelope version is set by passing in SoapEnvelope.VER11, which tells the kSOAP library that we’ll be using SOAP 1.1. We set the envelope’s dotNet property to true as the web service we’ll be consuming runs on Microsoft’s .NET framework.

envelope.dotNet = true;

Step 2: Configuring the Envelope

It is now time to configure the SOAP envelope by setting the request information. Start by importing the SoapObject class (org.ksoap2.serialization.SoapObject) and take a look at the code snippet below to see how to configure the envelope. We start by creating an instance of the SoapObject class, which requires two parameters, a namespace and a method name. You can add additional properties to the request using the addProperty method as shown below. In our example, I use addProperty to add the value in degrees Fahrenheit to the request.

String methodname = "FahrenheitToCelsius";
SoapObject request = new SoapObject(NAMESPACE, methodname);
request.addProperty("Fahrenheit", fValue);

You may be wondering where NAMESPACE is coming from. It’s a private static string that is defined elsewhere in the application as you can see below.

private static final String NAMESPACE = "http://www.w3schools.com/webservices/";

Step 3: Creating the Request

To send the request to the web service, we need to create an HTTP transport request. We’ll use the HttpTransportSE class (org.ksoap2.transport.HttpTransportSE) for this. Take a look at the example below.

HttpTransportSE ht = getHttpTransportSE();

As you may have guessed, getHttpTransportSE is another helper method and allows you to quickly create an HTTP transport object. It makes it less tedious to create an HTTP transport object every time you make a web service call. Take a look at its implementation below. To create an HttpTransportSE instance, we only need the base URL of the web service, which is another private static string as you can see below.

private final HttpTransportSE getHttpTransportSE() {
    HttpTransportSE ht = new HttpTransportSE(Proxy.NO_PROXY,MAIN_REQUEST_URL,60000);
    ht.debug = true;
    ht.setXmlVersionTag("<!--?xml version=\"1.0\" encoding= \"UTF-8\" ?-->");
    return ht;
}
private static final String MAIN_REQUEST_URL = "http://www.w3schools.com/webservices/tempconvert.asmx";

In getHttpTransportSE, we also configure the HttpTransportSE object. By passing Proxy.NO_PROXY as the first argument of the constructor, we specify that no proxy is used for the request. The third argument of the constructor sets the session timeout in milliseconds. To make debugging easier, we also set the object’s debug property to true. Any issues that pop up are logged to LogCat.

Step 4: Sending the Request

It is time to send the SOAP request to the web service. We do this over HTTP using the transport and envelope objects we created earlier. The HTTP transport object has a call method, which is used to add the SOAP action and envelope that we created earlier.

ht.call(SOAP_ACTION, envelope);

SOAP_ACTION is another private static string as you can see below.

private static final String SOAP_ACTION = "http://www.w3schools.com/webservices/FahrenheitToCelsius";

Step 5: Processing the Response

When the web service sends back a response, we’ll need to process it and handle any errors that may have been thrown. We can then display the data to the user. Take a look at the code snippet below in which we extract the response from the response envelope using the getResponse method.

SoapPrimitive resultsString = (SoapPrimitive)envelope.getResponse();

I’m using a SoapPrimitive type, but you can also use a SoapObject instance if the response from the web service is XML. You can then use the SoapObject instance to get the response values and store them in an array. Call toString on the SoapPrimitive object to convert the response to a simple string to use it in your application.

Take a look at the next code snippet in which I’ve implemented a method getCelsiusConversion. The method accepts a string variable as its only argument. The variable is added as a property to the SOAP request as we saw earlier in this tutorial. The variable the method consumes is the value in degrees Fahrenheit. This value is sent to and processed by the web service and we get back a response in degrees Celsius.

public String getCelsiusConversion(String fValue) {
        String data = null;
        String methodname = "FahrenheitToCelsius";
        SoapObject request = new SoapObject(NAMESPACE, methodname);
        request.addProperty("Fahrenheit", fValue);
        SoapSerializationEnvelope envelope = getSoapSerializationEnvelope(request);
        HttpTransportSE ht = getHttpTransportSE();
        try {
            ht.call(SOAP_ACTION, envelope);
            testHttpResponse(ht);
            SoapPrimitive resultsString = (SoapPrimitive)envelope.getResponse();
            List COOKIE_HEADER = (List)      ht.getServiceConnection().getResponseProperties();
            for (int i = 0; i < COOKIE_HEADER.size(); i++) {
                String key = COOKIE_HEADER.get(i).getKey();
                String value = COOKIE_HEADER.get(i).getValue();
                if (key != null && key.equalsIgnoreCase("set-cookie")) {
                    SoapRequests.SESSION_ID = value.trim();
                    Log.v("SOAP RETURN", "Cookie :" + SoapRequests.SESSION_ID);
                    break;
                }
            }
            data = resultsString.toString();
        } catch (SocketTimeoutException t) {
            t.printStackTrace();
        } catch (IOException i) {
            i.printStackTrace();
        } catch (Exception q) {
            q.printStackTrace();
        }
   return data;
}

I use two strings in getCelsiusConversion, data and methodname. The data variable will be returned by the method after the web service sent back a response, while methodname stores the name of the operation of the the web service that we’ll target and is used in the SoapObject instance.

You may have noticed the for loop in getCelsiusConversion, which isn’t part of the steps we’ve discussed earlier. When working with more complex web services, it is important to keep track of the current session. In the snippet below, I store the session and keep track of it each time I make a call to the web service.

for (int i = 0; i < COOKIE_HEADER.size(); i++) {
    String key = COOKIE_HEADER.get(i).getKey();
    String value = COOKIE_HEADER.get(i).getValue();
    if (key != null && key.equalsIgnoreCase("set-cookie")) {
        SoapRequests.SESSION_ID = value.trim();
        Log.v("SOAP RETURN", "Cookie :" + SoapRequests.SESSION_ID);
        break;
    }
}

4. Creating the user interface

Now that the hard work is behind us, it is time to make use of what we just created. To conclude this tutorial, I’ll show you how to create a simple user interface for converting a value in degrees Fahrenheit to a value in degrees Celsius and display the result on the user’s device.

Step 1: Create the layout

First, we need to create an XML file in the project’s layout folder. Take a look at the code snippet below. It is a simple illustration of a user interface created in XML.

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:orientation="vertical"
 android:layout_width="fill_parent"
 android:layout_height="fill_parent" /><EditText
 android:layout_width="200dp"
 android:layout_height="wrap_content"
 android:layout_gravity="center_horizontal"
 android:hint="Fahrenheit"
 android:inputType="number"
 android:id="@+id/value_to_convert" /><Button
 android:layout_width="200dp"
 android:layout_height="wrap_content"
 android:layout_gravity="center_horizontal"
 android:text="Convert to Celsius"
 android:id="@+id/convert" /><TextView
 android:layout_width="fill_parent"
 android:layout_height="wrap_content"
 android:gravity="center_horizontal"
 android:textSize="30dp"
 android:id="@+id/answer" /></LinearLayout>

We create three components, an EditText instance, a Button instance, and a TextView instance. The EditText instance is used to enter and capture the value that we intend to send to the web service. The button is used to run the thread that invokes getCelsiusConversion and the text view displays the response we get back from the web service.

Step 2: Create the Activity

The next step is creating an Activity instance to display the layout we just created. Take a look at the following code snippet. This shouldn’t be too surprising if you’ve developed Android applications before.

package com.example.KsoapExample;
import android.app.Activity;
import android.os.Bundle;
public class MyActivity extends Activity {
    /**
    * Called when the activity is first created.
    */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }
}

Now that we’ve taken care of the user interface, we can tie everything together. Take a look at the next code snippet to see how this is done.

package com.example.KsoapExample;
import android.app.Activity;
import android.os.Bundle;
public class MyActivity extends Activity {
    private TextView txt;
    private String celsius;
    /**
     * Called when the activity is first created.
     */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        final EditText edt = (EditText)findViewById(R.id.value_to_convert);
        Button btn = (Button)findViewById(R.id.convert);
        txt = (TextView)findViewById(R.id.answer);
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (edt.length() > 0) {
                    getCelsius(edt.getText().toString());
                } else {
                    txt.setText("Fahrenheit value can not be empty.");
                }
            }
        });
    }
}

In onCreate, we set a listener on the button, btn. We also double-check that a value is entered in the input field before sending it to the web service. In the button click listener, the value passed to getCelsius is cast to a string as the web service expects a string value. The implementation of getCelsius isn’t difficult as you can see below.

private final void getCelsius(final String toConvert) {
    new Thread(new Runnable() {
        @Override
        public void run() {
            SoapRequests ex = new SoapRequests();
            celsius = ex.getCelsiusConversion(toConvert);
            handler.sendEmptyMessage(0);
            }
    }).start();
}

In getCelsius, a new thread is created, which runs and creates an instance of the class that implements getCelsiusConversion. When we receive a response from the web service, we send a message to a handler to update the user interface by displaying the value in degrees Celsius to the user.

public Handler handler = new Handler(new Handler.Callback() {
    @Override
    public boolean handleMessage(Message msg) {
        switch (msg.what) {
            case 0:
                txt.setText(celsius);
                break;
        }
        return false;
    }
});

In the handler, we update the TextView instance with the value we received from the web service. Take a look at the final result below.



Conclusion

You should now be able to add the kSOAP library to a project and leverage it to make requests to a web service that uses the SOAP protocol. Working with the kSOAP library will become easier with a little practice and I therefore encourage you to try the Celsius to Fahrenheit conversion web service. Try out the example Android application that’s part of the tutorial for a bit of extra help.

Android First… Even When It’s Second

$
0
0

Designing for the Android platform isn’t easy, especially if you’re used to designing for iOS. Is porting your iOS designs to Android a viable option? It’s not, and I will tell you why.


The Backstory

Chances are, you got into mobile design so you could make iOS applications. Sooner or later though, you’ll find yourself being asked to port an iOS application to Android. Your boss tells you Android has something like 98% of the mobile market—okay, it’s about 60%—and it must be supported. “Think of all the people that cannot use our application!” he says. You ponder leaping off the balcony, but instead you decide to give it shot. After all, how hard can it be?

You talk to your designer friends, asking them what you should do. They complain about Android and about how hard it is to design for Android—not much of a help. You visit Dribbble, Behance, and the Google Play store looking for examples of good Android designs. Unfortunately, there’s not much to find. Even the big guys seem to have given up and jury-rigged iOS designs onto Android. You start wondering what kind of a mess you’ve gotten yourself into.

And evidently, after all that, your natural reaction is to contemplate the easy path. You’ll pump out the fastest possible iOS-to-Android design port you can and get this project off your plate and out of your life. My advice? Don’t do it! You can break this cycle—here’s how.


Start from Scratch

This step is crucial in the process as it will define your future workflow, your needs, and get you a realistic time estimate for the project. But you’ll have to approach this pretending that there is no iOS application. Start from scratch. Revisit your goals. Do some problem solving. (Re)engage the challenge of making a fantastic application. It’s a similar process to what you would have gone through to get that lovely iOS application out, back in the day.



Explore New Patterns

Immerse yourself in Android and its design patterns. Sure, it’s got some warts, but ask yourself—what does it get right? What do all the applications do, and what are users expecting? One of Android’s weaknesses is also one its greatest strengths: flexibility. Think about all the possibilities it has to offer. You can control the lock screen of a device or put a widget on its home screen. You’ll never find proper Facebook chat heads on iOS, Cover for iPhone, or a custom keyboard that you can use across applications. What can you do better on Android than on iOS?



New Rules for Typography

Use Roboto. Get over yourself and your love for Proxima Nova and Avenir. Roboto is a good typeface that adapts well to a lot of use cases. With six weights for each roman, italic, and condensed styles and an imposing library of glyphs, it can satisfy even the most demanding typographic tasks. It’s free and it’s pretty. Its overly geometrical shapes and Grotesque touches set a perfect rhythm for your application. It’ll give your application that spark that will make it feel like an Android application. Google knew what they were doing when they made it the default font for Android and chances are that they thought about their devices, operating system, and typographic needs way more than you ever will.



Responsive Design

Embrace responsiveness. It’s amazing how often mobile designers cry about screen sizes on Android and how well everything fits on their iPhone in one breath, and in the next, they talk about how awesome responsive websites are. Web designers have been dealing with this for more than twenty years now. This is exactly what you’re creating, a responsive application. There’s nothing new there. Start with the smallest low resolution screen and work your way up to the tablets. Remember that your phone application is also your tablet application. Resolutions are your breakpoints and it’s all one big liquid mass of grids, copy, and images.

It’s worth pointing out that, even though not mandatory, tablet optimization is an easy way to get noticed in the Google Play store or, if you’re lucky, get featured by Google. At this point, you’re competing with very few tablet application so go for it. Besides that, it will make you a better designer and broaden your skill set.



Second Device in Your Pocket

You must use Android as your main phone, at least until the project’s done. You’ll learn how the platform works and develop an eye for little Android details. Get to know the operating system and ask Android users what they like (and dislike) about Android. Take notes. Get to know the platform. Take another look at Explore New Patterns if you have to. That said, you can have an iPhone as well—you are a designer after all.


Make New Friends

Befriend your local Android engineer. Chances are that they’ve been using Android since you got your first iPhone. They know a lot about the platform, what it can do, what others are doing with it, and the tools you can use to craft an awesome experience. Together, you’ll come up with great approaches that neither of you would have thought of on your own. Your design gurus are right under your nose.


Get Noticed

The Android platform didn’t have the fortune to have a Steve Jobs to give it direction. This has resulted in mediocre user interface design and made most designers feel unconvinced. Every designer wants to be known for significant contributions to their field—that Android application is your opportunity to shine. The Android platform is maturing at a fast pace. It’s more robust than ever, but it’s still a toddler in terms of UI and UX. The little innovations that you come up with today may be the standards of tomorrow. You have the ability to help define the future of the operating system and get credit for your contributions.


Conclusion

To create a fantastic application on this foreign platform, you have to change how you feel about it. Learn to appreciate Android and love it as it is. Don’t port your application to Android, design it for Android. I’ll be the first to admit that designing for Android isn’t easy, but it’s the right thing to do. Good luck.

Resources

Here are few links for further reading and resources to get you started:

Working with NSURLSession: Part 4

$
0
0

In the previous tutorial, we started creating a simple podcast client to put what we’ve learned about NSURLSession into practice. So far, our podcast client can query the iTunes Search API, download a podcast feed, and display a list of episodes. In this tutorial, we zoom in on another interesting aspect of NSURLSession, out-of-process downloads. Let me show you how this works.


Introduction

In this fourth and final tutorial about NSURLSession, we’ll take a closer look at out-of-process tasks, download tasks in particular. Our podcast client is already able to show a list of episodes, but it currently lacks the ability to download individual episodes. That’ll be the focus of this tutorial.

Background Uploads and Downloads

Adding support for background uploads and downloads is surprisingly easy with NSURLSession. Apple refers to them as out-of-process uploads and downloads as the tasks are managed by a background daemon, not your application. Even if your application crashes during an upload or download task, the task continues in the background.

Overview

I’d like to take a few moments to take a closer look at how out-of-process tasks work. It’s pretty simple once you have a complete picture of the process. Enabling background uploads and downloads is nothing more than flipping a switch in your session’s configuration. With a properly configured session object, you are ready to schedule upload and download tasks in the background.

When an upload or download is initiated, a background daemon comes into existence. The daemon takes care of the task and sends updates to the application through the delegate protocols declared in the NSURLSession API. If your application stops running for some reason, the task continues in the background as it’s the daemon managing the task. The moment the task finishes, the application that created the task is notified. It reconnects with the background session that created the task and the daemon managing the task informs the session that the task finished and, in the case of a download task, hands the file over to the session. The session then invokes the appropriate delegate methods to make sure your application can take the appropriate actions, such as moving the file to a more permanent location. That’s enough theory for now. Let’s see what we need to do to implement out-of-process downloads in Singlecast.


1. Subclass UITableViewCell

Step 1: Update Main Storyboard

At the moment, we are using prototype cells to populate the table view. To give us a bit more flexibility, we need to create a UITableViewCell subclass. Open the main storyboard, select the table view of the MTViewController instance and set the number of prototype cells to 0.

Update the project's main storyboard.

Step 2: Create Subclass

Open Xcode’s File menu and choose New > File…. Create a new Objective-C class, name it MTEpisodeCell, and make sure it inherits from UITableViewCell. Tell Xcode where you’d like to store the class files and hit Create.

Create a subclass of UITableViewCell.

Step 3: Update Class Interface

The interface of MTEpisodeCell is simple as you can see in the code snippet below. All we do is declare a property progress of type float. We’ll use this to update and display the progress of the download task that we’ll use for downloading an episode.

#import <UIKit/UIKit.h>
@interface MTEpisodeCell : UITableViewCell
@property (assign, nonatomic) float progress;
@end

Step 4: Implement Class

The implementation of MTEpisodeCell is a bit more involved, but it isn’t complicated. Instead of using an instance of UIProgressView, we’ll fill the cell’s content view with a solid color to show the progress of the download task. We do this by adding a subview to the cell’s content view and updating its width whenever the cell’s progress property changes. Start by declaring a private property progressView of type UIView.

#import "MTEpisodeCell.h"
@interface MTEpisodeCell ()
@property (strong, nonatomic) UIView *progressView;
@end

We override the class’s designated initializer as shown below. Note how we ignore the style argument and pass UITableViewCellStyleSubtitle to the superclass’s designated initializer. This is important, because the table view will pass UITableViewCellStyleDefault as the cell’s style when we ask it for a new cell.

In the initializer, we set the background color of the text and detail text labels to [UIColor clearColor] and create the progress view. Two details are especially important. First, we insert the progress view as a subview of the cell’s content view at index 0 to make sure that it’s inserted below the text labels. Second, we invoke updateView to make sure that the frame of the progress view is updated to reflect the value of progress, which is set to 0 during the cell’s initialization.

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
    self = [super initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:reuseIdentifier];
    if (self) {
        // Helpers
        CGSize size = self.contentView.bounds.size;
        // Configure Labels
        [self.textLabel setBackgroundColor:[UIColor clearColor]];
        [self.detailTextLabel setBackgroundColor:[UIColor clearColor]];
        // Initialize Progress View
        self.progressView = [[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, size.width, size.height)];
        // Configure Progress View
        [self.progressView setAutoresizingMask:(UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleWidth)];
        [self.progressView setBackgroundColor:[UIColor colorWithRed:0.678 green:0.886 blue:0.557 alpha:1.0]];
        [self.contentView insertSubview:self.progressView atIndex:0];
        // Update View
        [self updateView];
    }
    return self;
}

Before we take a look at the implementation of updateView, we need to override the setter method of the progress property. The only change we make to the default implementation of setProgress: is invoke updateView when the _progress instance variable is updated. This ensures that the progress view is updated whenever we update the cell’s progress property.

- (void)setProgress:(CGFloat)progress {
    if (_progress != progress) {
        _progress = progress;
        // Update View
        [self updateView];
    }
}

In updateView, we calculate the new width of the progress view based on the value of the cell’s progress property.

- (void)updateView {
    // Helpers
    CGSize size = self.contentView.bounds.size;
    // Update Frame Progress View
    CGRect frame = self.progressView.frame;
    frame.size.width = size.width * self.progress;
    self.progressView.frame = frame;
}

Step 5: Use MTEpisodeCell

To make use of the MTEpisodeCell, we need to make a few changes in the MTViewController class. Start by adding an import statement for MTEpisodeCell.

#import "MTViewController.h"
#import "MWFeedParser.h"
#import "SVProgressHUD.h"
#import "MTEpisodeCell.h"
@interface MTViewController () <MWFeedParserDelegate>
@property (strong, nonatomic) NSDictionary *podcast;
@property (strong, nonatomic) NSMutableArray *episodes;
@property (strong, nonatomic) MWFeedParser *feedParser;
@end

In the view controller’s viewDidLoad method, invoke setupView, a helper method we’ll implement next.

- (void)viewDidLoad {
    [super viewDidLoad];
    // Setup View
    [self setupView];
    // Load Podcast
    [self loadPodcast];
    // Add Observer
    [[NSUserDefaults standardUserDefaults] addObserver:self forKeyPath:@"MTPodcast" options:NSKeyValueObservingOptionNew context:NULL];
}

In setupView, we invoke setupTableView, another helper method in which we tell the table view to use the MTEpisodeCell class whenever it needs a cell with a reuse identifier of EpisodeCell.

- (void)setupView {
    // Setup Table View
    [self setupTableView];
}
- (void)setupTableView {
    // Register Class for Cell Reuse
    [self.tableView registerClass:[MTEpisodeCell class] forCellReuseIdentifier:EpisodeCell];
}

Before we build the project and run the application, we need to update our implementation of tableView:cellForRowAtIndexPath: as shown below.

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    MTEpisodeCell *cell = (MTEpisodeCell *)[tableView dequeueReusableCellWithIdentifier:EpisodeCell forIndexPath:indexPath];
    // Fetch Feed Item
    MWFeedItem *feedItem = [self.episodes objectAtIndex:indexPath.row];
    // Configure Table View Cell
    [cell.textLabel setText:feedItem.title];
    [cell.detailTextLabel setText:[NSString stringWithFormat:@"%@", feedItem.date]];
    return cell;
}

Step 6: Build and Run

Run your application in the iOS Simulator or on a test device to see the result. If nothing has changed, then you’ve followed the steps correctly. All that we’ve done so far is replacing the prototype cells with instances of MTEpisodeCell.


2. Create Background Session

To enable out-of-process downloads, we need a session that is configured to support out-of-process downloads. This is surprisingly easy to do with the NSURLSession API. There a few gotchas though.

Step 1: Create session Property

Start by declaring a new property session of type NSURLSession in the MTViewController class and make the class conform to the NSURLSessionDelegate and NSURLSessionDownloadDelegate protocols.

#import "MTViewController.h"
#import "MWFeedParser.h"
#import "SVProgressHUD.h"
#import "MTEpisodeCell.h"
@interface MTViewController () <NSURLSessionDelegate, NSURLSessionDownloadDelegate, MWFeedParserDelegate>
@property (strong, nonatomic) NSDictionary *podcast;
@property (strong, nonatomic) NSMutableArray *episodes;
@property (strong, nonatomic) MWFeedParser *feedParser;
@property (strong, nonatomic) NSURLSession *session;
@end

In viewDidLoad, we set the session property by invoking backgroundSession on the view controller instance. This is one of the gotchas I was talking about.

- (void)viewDidLoad {
    [super viewDidLoad];
    // Setup View
    [self setupView];
    // Initialize Session
    [self setSession:[self backgroundSession]];
    // Load Podcast
    [self loadPodcast];
    // Add Observer
    [[NSUserDefaults standardUserDefaults] addObserver:self forKeyPath:@"MTPodcast" options:NSKeyValueObservingOptionNew context:NULL];
}

Let’s take a look at the implementation of backgroundSession. In backgroundSession, we statically declare a session variable and use dispatch_once (Grand Central Dispatch) to instantiate the background session. Even though this isn’t strictly necessary, it emphasizes the fact that we only need one background session at any time. This is a best practice that’s also mentioned in the WWDC session on the NSURLSession API.

In the dispatch_once block, we start by creating a NSURLSessionConfiguration object by invoking backgroundSessionConfiguration: and passing a string as an identifier. The identifier we pass uniquely identifies the background session, which is key as we’ll see a bit later. We then create a session instance by invoking sessionWithConfiguration:delegate:delegateQueue: and passing the session configuration object, setting the session’s delegate property, and passing nil as the third argument.

- (NSURLSession *)backgroundSession {
    static NSURLSession *session = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        // Session Configuration
        NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration backgroundSessionConfiguration:@"com.mobiletuts.Singlecast.BackgroundSession"];
        // Initialize Session
        session = [NSURLSession sessionWithConfiguration:sessionConfiguration delegate:self delegateQueue:nil];
    });
    return session;
}
By passing nil as the third argument of sessionWithConfiguration:delegate:delegateQueue:, the session creates a serial operation queue for us. This operation queue is used for performing the delegate method calls and completion handler calls.

3. Download Episode

Step 1: Create Download Task

It’s time to make use of the background session we created and put the MTEpisodeCell to use. Let’s start by implementing tableView:didSelectRowAtIndexPath:, a method of the UITableViewDelegate protocol. Its implementation is straightforward as you can see below. We fetch the correct MWFeedItem instance from the episodes array and pass it to downloadEpisodeWithFeedItem:.

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    [tableView deselectRowAtIndexPath:indexPath animated:YES];
    // Fetch Feed Item
    MWFeedItem *feedItem = [self.episodes objectAtIndex:indexPath.row];
    // Download Episode with Feed Item
    [self downloadEpisodeWithFeedItem:feedItem];
}

In downloadEpisodeWithFeedItem:, we extract the remote URL from the feed item by invoking urlForFeedItem:, create a download task by calling downloadTaskWithURL: on the background session, and send it a message of resume to start the download task.

- (void)downloadEpisodeWithFeedItem:(MWFeedItem *)feedItem {
    // Extract URL for Feed Item
    NSURL *URL = [self urlForFeedItem:feedItem];
    if (URL) {
        // Schedule Download Task
        [[self.session downloadTaskWithURL:URL] resume];
    }
}

As you may have guessed, urlForFeedItem: is a convenience method that we use. We’ll use it a few more times in this project. We obtain a reference to the feed item’s enclosures array, extract the first enclosure, and pull out the object for the url key. We create and return an NSURL instance.

- (NSURL *)urlForFeedItem:(MWFeedItem *)feedItem {
    NSURL *result = nil;
    // Extract Enclosures
    NSArray *enclosures = [feedItem enclosures];
    if (!enclosures || !enclosures.count) return result;
    NSDictionary *enclosure = [enclosures objectAtIndex:0];
    NSString *urlString = [enclosure objectForKey:@"url"];
    result = [NSURL URLWithString:urlString];
    return result;
}

We’re not done yet. Is the compiler giving you three warnings? That’s not surprising as we haven’t implemented the required methods of the NSURLSessionDelegate and NSURLSessionDownloadDelegate protocols yet. We also need to implement these methods if we want to show the progress of the download tasks.

Step 2: Implementing Protocol(s)

The first method we need to implement is URLSession:downloadTask:didResumeAtOffset:. This method is invoked if a download task is resumed. Because this is something we won’t cover in this tutorial, we simply log a message to Xcode’s console.

- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes {
    NSLog(@"%s", __PRETTY_FUNCTION__);
}

More interesting is the implementation of URLSession:downloadTask:didWriteData:totalBytesWritten:totalBytesExpectedToWrite:. This method is invoked every time a few bytes have been downloaded by the session. In this delegate method, we calculate the progress, fetch the correct cell, and update the cell’s progress property, which in turn updates the cell’s progress view. Have you spotted the dispatch_async call? There’s no guarantee that the delegate method is invoked on the main thread. Since we update the user interface by setting the cell’s progress, we need to update the cell’s progress property on the main thread.

- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite {
    // Calculate Progress
    double progress = (double)totalBytesWritten / (double)totalBytesExpectedToWrite;
    // Update Table View Cell
    MTEpisodeCell *cell = [self cellForForDownloadTask:downloadTask];
    dispatch_async(dispatch_get_main_queue(), ^{
        [cell setProgress:progress];
    });
}

The implementation of cellForForDownloadTask: is straightforward. We pull the remote URL from the download task using its originalRequest property and loop over the feed items in the episodes array until we have a match. When we’ve found a match, we ask the table view for the corresponding cell and return it.

- (MTEpisodeCell *)cellForForDownloadTask:(NSURLSessionDownloadTask *)downloadTask {
    // Helpers
    MTEpisodeCell *cell = nil;
    NSURL *URL = [[downloadTask originalRequest] URL];
    for (MWFeedItem *feedItem in self.episodes) {
        NSURL *feedItemURL = [self urlForFeedItem:feedItem];
        if ([URL isEqual:feedItemURL]) {
            NSUInteger index = [self.episodes indexOfObject:feedItem];
            cell = (MTEpisodeCell *)[self.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:index inSection:0]];
            break;
        }
    }
    return cell;
}

The third delegate method of the NSURLSessionDownloadDelegate protocol that we need to implement is URLSession:downloadTask:didFinishDownloadingToURL:. As I mentioned in the previous tutorials, one of the advantages of the NSURLSession API is that downloads are immediately written to disk. The result is that we are passed a local URL in URLSession:downloadTask:didFinishDownloadingToURL:. However, the local URL that we receive, points to a temporary file. It is our responsibility to move the file to a more permanent location and that’s exactly what we do in URLSession:downloadTask:didFinishDownloadingToURL:.

- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location {
    // Write File to Disk
    [self moveFileWithURL:location downloadTask:downloadTask];
}

In moveFileWithURL:downloadTask:, we extract the episode’s file name from the download task and create a URL in the application’s Documents directory by invoking URLForEpisodeWithName:. If the temporary file that we received from the background session points to a valid file, we move that file to its new home in the application’s Documents directory.

- (void)moveFileWithURL:(NSURL *)URL downloadTask:(NSURLSessionDownloadTask *)downloadTask {
    // Filename
    NSString *fileName = [[[downloadTask originalRequest] URL] lastPathComponent];
    // Local URL
    NSURL *localURL = [self URLForEpisodeWithName:fileName];
    NSFileManager *fm = [NSFileManager defaultManager];
    if ([fm fileExistsAtPath:[URL path]]) {
        NSError *error = nil;
        [fm moveItemAtURL:URL toURL:localURL error:&error];
        if (error) {
            NSLog(@"Unable to move temporary file to destination. %@, %@", error, error.userInfo);
        }
    }
}
I use a lot of helper methods in my iOS projects, because it makes for DRY code. It’s also good practice to create methods that only do one thing. Testing becomes much easier that way.

URLForEpisodeWithName: is another helper method, which invokes episodesDirectory. In URLForEpisodeWithName:, we append the name argument to the Episodes directory, which is located in the application’s Documents directory.

- (NSURL *)URLForEpisodeWithName:(NSString *)name {
    if (!name) return nil;
    return [self.episodesDirectory URLByAppendingPathComponent:name];
}

In episodesDirectory, we create the URL for the Episodes directory and create the directory if it doesn’t exist yet.

- (NSURL *)episodesDirectory {
    NSURL *documents = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
    NSURL *episodes = [documents URLByAppendingPathComponent:@"Episodes"];
    NSFileManager *fm = [NSFileManager defaultManager];
    if (![fm fileExistsAtPath:[episodes path]]) {
        NSError *error = nil;
        [fm createDirectoryAtURL:episodes withIntermediateDirectories:YES attributes:nil error:&error];
        if (error) {
            NSLog(@"Unable to create episodes directory. %@, %@", error, error.userInfo);
        }
    }
    return episodes;
}

Step 3: Build and Run

Run the application and test the result by downloading an episode from the list of episodes. You should see the table view cell’s progress view progress from left to right reflecting the progress of the download task. There are a few issues though. Have you tried scrolling through the table view? That doesn’t look right. Let’s fix that.


4. Create a Progress Buffer

Because the table view reuses cells as much as possible, we need to make sure that each cell properly reflects the download state of the episode that it represents. We can fix this in several ways. One approach is to use an object that keeps track of the progress of each download task, including the download tasks that have already completed.

Step 1: Declare a Property

Let’s start by declaring a new private property progressBuffer of type NSMutableDictionary in the MTViewController class.

#import "MTViewController.h"
#import "MWFeedParser.h"
#import "SVProgressHUD.h"
#import "MTEpisodeCell.h"
@interface MTViewController () <NSURLSessionDelegate, NSURLSessionDownloadDelegate, MWFeedParserDelegate>
@property (strong, nonatomic) NSDictionary *podcast;
@property (strong, nonatomic) NSMutableArray *episodes;
@property (strong, nonatomic) MWFeedParser *feedParser;
@property (strong, nonatomic) NSURLSession *session;
@property (strong, nonatomic) NSMutableDictionary *progressBuffer;
@end

Step 2: Initialize Buffer

In viewDidLoad, we initialize the progress buffer as shown below.

- (void)viewDidLoad {
    [super viewDidLoad];
    // Setup View
    [self setupView];
    // Initialize Session
    [self setSession:[self backgroundSession]];
    // Initialize Progress Buffer
    [self setProgressBuffer:[NSMutableDictionary dictionary]];
    // Load Podcast
    [self loadPodcast];
    // Add Observer
    [[NSUserDefaults standardUserDefaults] addObserver:self forKeyPath:@"MTPodcast" options:NSKeyValueObservingOptionNew context:NULL];
}

Step 3: Update Table View Cells

The key that we’ll use in the dictionary is the remote URL of the corresponding feed item. With this in mind, we can update the tableView:cellForRowAtIndexPath: method as shown below. We pull the remote URL from the feed item and ask progressBuffer for the value for the key that corresponds to the remote URL. If the value isn’t nil, we set the cell’s progress property to that value, otherwise we set the progress property of the cell to 0.0, which hides the progress view by setting its width to 0.0.

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    MTEpisodeCell *cell = (MTEpisodeCell *)[tableView dequeueReusableCellWithIdentifier:EpisodeCell forIndexPath:indexPath];
    // Fetch Feed Item
    MWFeedItem *feedItem = [self.episodes objectAtIndex:indexPath.row];
    NSURL *URL = [self urlForFeedItem:feedItem];
    // Configure Table View Cell
    [cell.textLabel setText:feedItem.title];
    [cell.detailTextLabel setText:[NSString stringWithFormat:@"%@", feedItem.date]];
    NSNumber *progress = [self.progressBuffer objectForKey:[URL absoluteString]];
    if (!progress) progress = @(0.0);
    [cell setProgress:[progress floatValue]];
    return cell;
}

Step 4: Avoid Duplicates

We can also use the progress buffer to prevent users from downloading the same episode twice. Take a look at the updated implementation of tableView:didSelectRowAtIndexPath:. We take the same steps we took in tableView:cellForRowAtIndexPath: to extract the progress value from the progress buffer. Only when the progress value is nil, we download the episode.

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    [tableView deselectRowAtIndexPath:indexPath animated:YES];
    // Fetch Feed Item
    MWFeedItem *feedItem = [self.episodes objectAtIndex:indexPath.row];
    // URL for Feed Item
    NSURL *URL = [self urlForFeedItem:feedItem];
    if (![self.progressBuffer objectForKey:[URL absoluteString]]) {
        // Download Episode with Feed Item
        [self downloadEpisodeWithFeedItem:feedItem];
    }
}

Step 5: Update Buffer

The progress buffer only works in its current implementation if we keep it up to date. This means that we need to update the URLSession:downloadTask:didWriteData:totalBytesWritten:totalBytesExpectedToWrite: method as well. All we do is store the new progress value in the progress buffer.

- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite {
    // Calculate Progress
    double progress = (double)totalBytesWritten / (double)totalBytesExpectedToWrite;
    // Update Progress Buffer
    NSURL *URL = [[downloadTask originalRequest] URL];
    [self.progressBuffer setObject:@(progress) forKey:[URL absoluteString]];
    // Update Table View Cell
    MTEpisodeCell *cell = [self cellForForDownloadTask:downloadTask];
    dispatch_async(dispatch_get_main_queue(), ^{
        [cell setProgress:progress];
    });
}

In downloadEpisodeWithFeedItem:, we set the progress value to 0.0 when the download task starts.

- (void)downloadEpisodeWithFeedItem:(MWFeedItem *)feedItem {
    // Extract URL for Feed Item
    NSURL *URL = [self urlForFeedItem:feedItem];
    if (URL) {
        // Schedule Download Task
        [[self.session downloadTaskWithURL:URL] resume];
        // Update Progress Buffer
        [self.progressBuffer setObject:@(0.0) forKey:[URL absoluteString]];
    }
}

The session delegate is notified when a download task finishes. In URLSession:downloadTask:didFinishDownloadingToURL:, we set the progress value to 1.0.

- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location {
    // Write File to Disk
    [self moveFileWithURL:location downloadTask:downloadTask];
    // Update Progress Buffer
    NSURL *URL = [[downloadTask originalRequest] URL];
    [self.progressBuffer setObject:@(1.0) forKey:[URL absoluteString]];
}

Step 6: Restore Buffer

At the moment, the progress buffer is only stored in memory, which means that it’s cleared between application launches. We could write its contents to disk, but to keep this application simple we are going to restore or recreate the buffer by checking which episodes have already been downloaded. The feedParser:didParseFeedItem: method, part of the MWFeedParserDelegate protocol, is invoked for every item in the feed. In this method, we pull the remote URL from the feed item, create the corresponding local URL, and check if the file exists. If it does, then we set the corresponding progress value for that feed item to 1.0 to indicate that it’s already been downloaded.

- (void)feedParser:(MWFeedParser *)parser didParseFeedItem:(MWFeedItem *)item {
    if (!self.episodes) {
        self.episodes = [NSMutableArray array];
    }
    [self.episodes addObject:item];
    // Update Progress Buffer
    NSURL *URL = [self urlForFeedItem:item];
    NSURL *localURL = [self URLForEpisodeWithName:[URL lastPathComponent]];
    if ([[NSFileManager defaultManager] fileExistsAtPath:[localURL path]]) {
        [self.progressBuffer setObject:@(1.0) forKey:[URL absoluteString]];
    }
}

Step 7: Rinse and Repeat

Run the application one more time to see if the issues with the table view are resolved. The application should now also remember which episodes have already been downloaded.


5. Being a Good Citizen

It’s important that our application is a good citizen by not wasting more CPU cycles or consume more battery power than needed. What does this mean for our podcast client. When a download task is started by our application and the application goes to the background, the background daemon that manages our application’s download task notifies our application through the background session that the download task has finished. If necessary, the background daemon will launch our application so that it can respond to these notifications and process the downloaded file.

In our example, we don’t need to do anything special to make sure that our application reconnects to the original background session. This is taken care of by the MTViewController instance. However, we do have to notify the operating system when our application has finished processing the download(s) by invoking a background completion handler.

When our application is woken up by the operating system to respond to the notifications of the background session, the application delegate is sent a message of application:handleEventsForBackgroundURLSession:completionHandler:. In this method, we can reconnect to the background session, if necessary, and invoke the completion handler that is passed to us. By invoking the completion handler, the operating system knows that our application no longer needs to run in the background. This is important for optimizing battery life. How do we do this in practice?

Step 1: Declare a Property

We first need to declare a property on the MTAppDelegate class to keep a reference to the completion handler that we get from application:handleEventsForBackgroundURLSession:completionHandler:. The property needs to be public. The reason for this will become clear in a moment.

#import <UIKit/UIKit.h>
@interface MTAppDelegate : UIResponder <UIApplicationDelegate>
@property (strong, nonatomic) UIWindow *window;
@property (copy, nonatomic) void (^backgroundSessionCompletionHandler)();
@end

Step 2: Implement Callback

In application:handleEventsForBackgroundURLSession:completionHandler:, we store the completion handler in backgroundSessionCompletionHandler, which we declared a moment ago.

- (void)application:(UIApplication *)application handleEventsForBackgroundURLSession:(NSString *)identifier completionHandler:(void (^)())completionHandler {
    [self setBackgroundSessionCompletionHandler:completionHandler];
}

Step 3: Invoke Background Completion Handler

In the MTViewController class, we start by adding an import statement for the MTAppDelegate class.

#import "MTViewController.h"
#import "MWFeedParser.h"
#import "MTAppDelegate.h"
#import "SVProgressHUD.h"
#import "MTEpisodeCell.h"
@interface MTViewController () <NSURLSessionDelegate, NSURLSessionDownloadDelegate, MWFeedParserDelegate>
@property (strong, nonatomic) NSDictionary *podcast;
@property (strong, nonatomic) NSMutableArray *episodes;
@property (strong, nonatomic) MWFeedParser *feedParser;
@property (strong, nonatomic) NSURLSession *session;
@property (strong, nonatomic) NSMutableDictionary *progressBuffer;
@end

We then implement another helper method, invokeBackgroundSessionCompletionHandler, which invokes the background completion handler stored in the application delegate’s backgroundSessionCompletionHandler property. In this method, we ask the background session for all its running tasks. If there are no tasks running, we get a reference to the application delegate’s background completion handler and, if it isn’t nil, we invoke it and set it to nil.

- (void)invokeBackgroundSessionCompletionHandler {
    [self.session getTasksWithCompletionHandler:^(NSArray *dataTasks, NSArray *uploadTasks, NSArray *downloadTasks) {
        NSUInteger count = [dataTasks count] + [uploadTasks count] + [downloadTasks count];
        if (!count) {
            MTAppDelegate *applicationDelegate = (MTAppDelegate *)[[UIApplication sharedApplication] delegate];
            void (^backgroundSessionCompletionHandler)() = [applicationDelegate backgroundSessionCompletionHandler];
            if (backgroundSessionCompletionHandler) {
                [applicationDelegate setBackgroundSessionCompletionHandler:nil];
                backgroundSessionCompletionHandler();
            }
        }
    }];
}

Wait a minute. When do we invoke invokeBackgroundSessionCompletionHandler? We do this every time a download task finishes. In other words, we invoke this method in URLSession:downloadTask:didFinishDownloadingToURL: as shown below.

- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location {
    // Write File to Disk
    [self moveFileWithURL:location downloadTask:downloadTask];
    // Update Progress Buffer
    NSURL *URL = [[downloadTask originalRequest] URL];
    [self.progressBuffer setObject:@(1.0) forKey:[URL absoluteString]];
    // Invoke Background Completion Handler
    [self invokeBackgroundSessionCompletionHandler];
}

6. Wrapping Up

I hope you agree that our podcast client isn’t ready for the App Store just yet since one of the key features, playing podcasts, is still missing. As I mentioned in the previous tutorial, the focus of this project wasn’t creating a full-featured podcast client. The goal of this project was illustrating how to leverage the NSURLSession API to search the iTunes Search API and download podcast episodes using data and out-of-process download tasks respectively. You should now have a basic understanding of the NSURLSession API as well as out-of-process tasks.


Conclusion

By creating a simple podcast client, we have taken a close look at data and download tasks. We’ve also learned how easy it is to schedule download tasks in the background. The NSURLSession API is an important step forward for both iOS and OS X, and I encourage you to take advantage of this easy to use and flexible suite of classes. In the final installment of this series, I will take a look at AFNetworking 2.0. Why is it a milestone release? When should you use it? And how does it compare to the NSURLSession API?

Android 2013: A Year in Review and 2014 Predictions

$
0
0

It was another strong and, may I say, dominant year for the Android platform. It continued to dominate in market share and climb in numbers. Countless devices were released featuring the popular, mobile operating system and not all of those devices were smartphones or tablets. Android is making headway in new territories. 2013 was a busy year for the green robot. Now that the year has come to a close, it’s time to recap the action.


Market Share

Android’s market share in 2013 was impressive. Google reported that there’d been over 900,000 activations and IDC (International Data Corporation) data showed that four out of five phones shipped with the Android operating system on it. There was good news on the Google Play front as well. Google Play is accounting for 75% of all app downloads.

Unfortunately, market share doesn’t equal profit. In 2013, Apple’s App Store generated over $10 billion with December accounting for $1 billion.

From a developer’s perspective, these numbers are encouraging and the same is true for Google Play. However, it remains a fact that Android users spend less money on applications than iOS users. Apple’s mobile platform remains more profitable than Google’s.


API distribution

In 2013, Android made good progress addressing the operating system’s problematic fragmentation. Android versions below 2.2 have virtually disappeared with 2.2 (Froyo) and 3.2 (Honeycomb) following suit.

As of January 2014, more than 50% of Android devices are running a flavor of Jelly Bean, while 2.3 (Gingerbread) and 4.0 (Ice cream sandwich) declined considerable in 2013. This is a good sign, though, as it indicates that attempts to reduce Android’s fragmentation are heading the right direction.

December 2012
VersionCodenameAPIDistribution
1.5Cupcake30.1%
1.6Donut40.3%
2.1Eclaire72.7%
2.2Froyo810.3%
2.2-2.3.2Ginger Bread90.2%
2.3.3-2.3.7Ginger Bread1050.6%
3.1Honeycomb120.4%
3.2Honeycomb131.2%
4.0.3-4.0.4Ice Cream Sandwich1527.5%
4.1Jelly Bean165.9%
4.2Jelly Bean170.8%
December 2013
VersionCodenameAPIDistribution
2.2Froyo81.6%
2.3.3-2.3.7Ginger Bread1024.1%
3.2Honeycomb130.1%
4.0.3-4.0.4Ice Cream Sandwich1518.6%
4.1Jelly Bean1637.4%
4.2Jelly Bean1712.9%
4.3Jelly Bean184.2%
4.4KitKat191.1%

Hardware

Nexus Line

The Nexus line was updated with two new entries in 2013. LG’s Nexus 5 was the successor to the Nexus 4 and, once again, it was LG manufacturing the device. The device itself didn’t ship with revolutionary features for its time of launch, it was the KitKat experience and the mid-market price tag of $349 that made for a desirable device. Asus’ Nexus 7 also received a refresh, which included a 1200 x 1920 display and 2GB of RAM.


Gaming

Android made great strides as a gaming platform with a few new and notable gaming systems using Android as their operating system. One of the biggest hits was the Ouya. The tiny console’s goal is to bring cost-effective hardware into the living room and to provide a platform that is open to small developers. The concept proved a major hit on Kickstarter. It reached its goal in just eight hours.

And then there was the NVidea Shield, ultimate gaming and portable entertainment as NVidia puts it. The Shield is a powerful handheld gaming console with access to Google play and the ability to stream games from compatible computers. It makes for an impressive and unique device, but the key question is whether it will make a dent in the incredibly competitive gaming landscape.

Glass

Google Glass continued to grow with many developers and technology enthusiasts joining the Glass Explorers Program. Early adopters and developers were excited enough by the product to spend the $1,500 to join the program. Most of the program’s participants continue to give overwhelmingly positive responses so it seems Google is doing something right with Google Glass. People wearing Google Glass still experience social awkwardness and tension and it will therefore be interesting to see if this holds back the adoption and growth of Google Glass.

Galaxy Gear

In 2013, wearables started to become mainstream. Really? No. Not really. However, the Pebble smartwatch was finally released after its successful Kickstarter campaign. In addition, Sony released its second generation of smartwatch and Samsung launched the Galaxy Gear in the fall.

None managed to win over the average consumer and they failed to prove the usefulness of a smartwatch to the mass market. This leaves the market wide open for 2014 and with big names like Apple, Google, and Microsoft rumored to be introducing products in this category, it could become an interesting year for the smartwatch. Let’s hope the competition in this space will lead to spectacular innovation so that we will start to see more useful and practical implementation of smartwatches in this market segment.

Google TV

It was a slow year for Google TV. There were few additions to the market and none that were noteworthy. It was announced that Android version 4.2.2 will eventually make its way to compatible set-top boxes and that it will also get support for Google’s Chromecast at some point.

Chromecast

Speaking of Google’s Chromecast, on July 24, Google announced the Chromecast. The Chromecast is a $35 dongle that allows consumers to stream content from a computer or mobile device to their TV over Wi-Fi. The cheap dongle was very well received and it even made it in TIME’s Top 10 Gadgets of 2013.


KitKat

On October 31, Google released Android 4.4, also known as KitKat. The release came as a surprise to many as Key Lime Pie and 5.0 were expected instead of KitKat. KitKat was also the first version to be named after a branded product.

The update itself is substantial and includes many new features. The update’s theme was reducing the operating system’s footprint and making it more efficient in terms of power consumption and performance on older and low-end devices.

From a developer’s perspective, it is interesting to note the update also introduced new memory management tools, new storage access and printing frameworks, and host card emulation. You can read a more comprehensive review of Android KitKat on Mobiletuts+.


CyanogenMod

One of last year’s most significant success stories came from Android’s community operating system, CyanogenMod. CyanogenMod has been helping Android users for years getting the best from their devices, long after official updates and patches had stopped. In 2013, the people behind the popular Android distribution was able to raise funding and create a company. The not so surprising result is that rumors have started circulating about the possibility of an official CyanogenMod smartphone in the not so distant future.



Android Studio

During last year’s Google I/O developer conference, Google announced a new IDE (Integrated Development Environment) for the Android platform, Android Studio. It was made available to developers in June as an early access preview. The preview is available for download on Windows, OS X, and Linux from the Android developer website.

Android Studio is based on IntelliJ IDEA, a popular Java IDE developed by JetBrains. Based on early reviews and feedback, it seems to be well received by the Android developer community. Despite a plenty of updates, the IDE is still an early preview and prone to bugs. Eclipse is still preferred by most developers.


Google Play Game Services

In 2013, Google Play and a number of other core applications and services received significant updates. These updates took the spotlight at Google I/O 2013. With more than 900,000 daily activations, it was time to refine the user experience and improve the operating system’s services.

The biggest announcement was Google Play game services SDK enabling developers to create games with achievements, leaderboards, real-time multiplayer. Game data can be stored in the cloud and users can use their Google+ account to sign in.


Predictions

Convergence

My prediction is that 2014 will be the year of convergence. There’s currently an Android device for nearly every situation imaginable and the focus for this year will be on making sure that the user experience is less fragmented and more alike across devices.

Devices

We can expect another update of the operating system this year, which will most likely coincide with a refresh of the Nexus line. The Nexus 10 will receive an update or a sibling and the release of a Nexus 6 is a safe bet.

The key players in the smartphone and tablet market will no doubt release new products, but I think it’s the console market that will surprise us this year. There’s a new breed of consoles, microconsoles, that are trying to enter the console market, such as the Nvidia’s Shield, Valve’s Steam Machine, and, of course, the crowdfunded Ouya. Valve’s Steam Machine in particular is an interesting concept as it lets manufacturers create consoles based on a detailed specification. Alienware, for example, recently announced that it will be releasing a Steam Machine in September. It will be an interesting year for gamers. That’s for sure.

In 2013, several companies entered the wearables category and this trend will not stop in 2014. The rumors about an Apple smartwatch have subsided a little, but where there’s smoke, there’s fire. Right?

Android

I hope we get to see Android 5.0 in 2014 as this milestone release is long overdue. The update may introduce improvements related to multitasking, better Chromecast integration, and deeper integration of Google Now. As for Google Now, new voice commands will be added as well as improvements to voice search that build upon the OK Google features added to Google Now in 2013.

Many consumers hope to see KitKat on their devices at some point. With the market as competitive as it is, failing to quickly and smoothly update handsets could put several manufactures into trouble. Fast and smooth updates of the operating system remain one of the key advantages iOS has over Android. Long gone are the days when a company could issue a single update to a device in its first year and then leave it at that. Failing to keep handsets updated will definitely cause customers to switch.

Google has invested heavily into making KitKat compatible with a wide range of devices including less powerful low-end devices. It goes without saying that developers support this wholeheartedly. Android fragmentation continues to be one of Android’s primary gripes that also affect consumers. KitKat will hopefully be roled out to most of the new devices that we’ll see in 2014, allowing developers to leverage KitKat’s new features in their applications.


Conclusion

2014 is set to be a frantic year for Android. In many aspects, it will be similar to 2010. This time, however, it won’t be smartphones being released in every shape, size, and form factor. Instead, it’ll be wearables, game consoles, and television sets. We’ll be spoiled with plenty of press releases, lots of excitement, and more than enough early adopters regretting their purchase.

Developers too have a lot to look forward to. The first version of Android Studio will very likely see the light of day in 2014. New devices and possibly new markets will continue to please and tempt developers, but I will be spending 2014 tweaking images for high-resolution displays.

What do you think 2014 will bring? Share your thought in the comment’s below or let me know on Twitter or Google+.

Viewing all 1836 articles
Browse latest View live