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

Android SDK: User Interface Design

$
0
0

In this series we’re learning about Android SDK development from scratch! In this tutorial, we will build a simple user interface layout with a few visual elements.

Introduction

We will add the layout to the first app project we created and explored over the past few tutorials and we will continue working on the project throughout this series. We will primarily work with XML and the Eclipse ADT interface in this part, but will start to use a little Java in the next two parts. Both XML and Java coding are involved in many aspects of Android development, so you will need to get a grasp of the basics in these languages if you have not already. If you are new to either language, you will use what we learn in this series as a foundation for future learning.


1. XML Basics

Before we start on layouts, let’s run through some XML basics for those who haven’t used the markup language before. If you are already familiar with XML, skip to part two of this tutorial. XML is a language that stores data values. XML files are used for many different purposes. They function like databases in some projects and often model Web page output. If you’ve used HTML before you should be familiar with the essential features.

In XML, data values are stored in elements. A single element typically includes an opening tag and a closing tag as in this example:

<product>Onion</product>

As you can see, the opening tag and closing tag are the same except for the leading slash “/” indicating the closing tag. The data value in this case is the element content, the text string “Onion”. The opening tag can also contain attributes for additional information about the data item:

<product type="vegetable">Onion</product>

Each attribute has a name and a value, with the value enclosed in quotes. Elements can also contain other elements:

<section name="food"><product type="vegetable">Onion</product><product type="fruit">Banana</product></section>

In such a structure we say that the section element is parent and the products are child elements. The two child elements are also referred to as siblings. In an XML document, there must be one root element which acts as parent to all elements contained, or “nested”, within it. This creates a tree structure, with child elements branching out from parent elements. A child element can also be a parent element if it also contains further child elements.

One other XML structure you will see is the self-closing element, which does not have separate opening and closing tags:

<order number="12345" customerID="a4d45s"/>

The slash “/” character at the end of the element closes it.

All of the resource files we work with on Android use XML markup, including layout files, drawables, data values, and the Manifest.


2. Android Layouts

Step 1

When you work with XML in the Eclipse IDE with the ADT installed, the coding process is a little easier by the contextual prompts you will see as you type. Open your new app’s main layout file in the editor and make sure you have the XML editing tab selected so that we can work on the code directly. This is the layout for the main screen users see when the app is launched. Eclipse entered a basic layout for us to work with:

<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:layout_width="wrap_content"
		android:layout_height="wrap_content"
		android:text="@string/hello_world" /></RelativeLayout>

As you can see, the root element is a layout element, in this case a RelativeLayout. There are a few different layout types on Android and you can nest layouts inside one another. The root layout element here has a number of attributes indicating additional information about the layout, such as the width, height, and margins. Inside the layout element is a TextView– this lets you display a text string. The TextView is a type of View. Views are the visible and interactive elements that make up your app UI. Therefore each screen in your app is a selection of Views arranged using one or more layouts. In Android, the layouts are described as ViewGroup objects, with each ViewGroup containing one or more Views.

Step 2

To focus on the basic building blocks of a layout, delete the existing content of your main layout file and we will start from scratch. As we mentioned earlier in the series, you can build your layouts and Views in Java code, but the Android tools lend themselves to use XML for designing your app UIs, since you can see the visible results while you build the elements. There may be cases when it makes sense to build some or all of a UI in Java, but for the most part you should use XML. This practice also keeps the application logic and presentation elements separate.

The first task to build a layout is to choose a layout type. Let’s start with one of the simplest: a LinearLayout.

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
	android:layout_width="fill_parent"
	android:layout_height="fill_parent"
	android:orientation="vertical" ><!-- views go here --></LinearLayout>

The LinearLayout arranges the Views we want to display along either a horizontal or vertical line. In this case the orientation is vertical so each View is added to the screen below the last. A horizontal layout adds Views left to right. The layout fills the available space both horizontally and vertically using the “layout_width” and “layout_height” attributes (on Android these are often referred to as layout parameters).

Add a new line after the line in which the “layout_height” is declared. Start typing an attribute by entering “android:”. When you type the colon, Eclipse should prompt you with a list of relevant attributes. You can either continue typing to narrow the suggestion list or scroll through it to select one with your mouse. Select the “android:gravity” attribute.

Attribute Prompt

Enter “center_horizontal” as the gravity value so that the contained elements is displayed centered on the X axis:

android:gravity="center_horizontal"

This applies to everything inside the layout. We can set several additional display properties such as padding, margins, and backgrounds. But let’s keep things simple for now.


3. Adding Views

Step 1

Next, we’ll add some Views to the layout. The Views are the visible elements in the UI. Let’s add some text and a button. Inside the LinearLayout element (between the opening and closing tags), start by typing “<” and Eclipse should prompt you with a list of available elements as it did with the attribute.

Element Prompt

Select TextView from the list. Notice that this is a self-closing element, most of the Views are. Give the TextView attributes, starting with the layout width and height (type “android:” and use the prompts):

<TextView
	android:layout_width="wrap_content"
	android:layout_height="wrap_content" />

We set the View wide enough to accommodate its content using “wrap_content”, rather than filling the parent as we did with the layout. Add another attribute to the TextView, this time listing the text string to display within it:

android:text="Hello there"

When you save the file you will see that Eclipse displays a warning message. If you hover over it, the editor margin displays the text, which also is displayed in the Problems view. It reads “Hardcoded string … should use @string resource”. The recommended practice is to store each text string value as a values resource, rather than including it directly in the layout XML. Although this may seem extra work for no reason at first, it is worth getting into the habit of doing so, as you will see the benefit of it when your projects get bigger. Find the “res/values/strings.xml” file in your Package Explorer and open it. Switch to the “strings.xml” tab to edit the code.

Strings Edit

You will see that Eclipse has added a few strings already. Add another, giving it a name and value:

<string name="hello">Hello there</string>

This means that if you use the same string in more than one place in the app UI, and if you later decide to change it, you only have to do so in one place. Save the strings file and switch back to the layout file. Alter your TextView“text” attribute to refer to the string in the values file:

android:text="@string/hello"

We use the string name preceded by “@string” to tell the Android tools where to find the string resource. The warning should disappear. Eclipse does this often while you are coding, to indicate errors and warnings. You can choose whether or not to observe warnings, but for errors you need to take action or your app will not function.

Step 2

After the TextView, add a Button:

<Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/click" />

The Button uses the same attributes as the TextView in this case. But many more attributes are possible, and in general different views require different attributes. The “text” attribute value appears on the button. Add the string to your “res/values/strings.xml” file as before:

<string name="click">Click Me!</string>

In the next tutorial we will handle clicks on the button. Switch back to your layout file. Look at the Outline view to the right of the editor, it displays another interface to the file elements. Double-clicking the listed items jumps to their location in code. You can also expand and collapse parent elements. This is particularly useful when your layouts become more complex.

Layout Outline View
Tip: To tidy up any file that’s opened in the Eclipse editor, select all using “Ctrl+A” then click “Ctrl+I” to apply indentation.

4. Graphical Layout

Step 1

Make sure your layout file is saved and switch to the Graphical Layout tab.

Graphical Layout Tab

You can see a visual representation of your layout as you design it. The Palette area to the left allows you to select UI items and drag them onto the layout. However, to begin with, you should use XML at least until you have a grasp of the basics. XML gives you control over the details, so even if you do use the graphical tools, you will likely need to edit the XML results.

At the top of the Graphical Layout view there is a drop-down list from which you can select devices to see your layout on, as well as tools to switch orientation and zoom. Experiment with the Graphical Layout controls as you design your layouts. There are several other layout elements and settings to explore as well.

Step 2

Initially you might notice that in the layout visible elements appear very close to the top edge of the screen. Let’s sort this out. Switch back to the XML editing tab and add a margin attribute to the LinearLayout:

android:layout_margin="10dp"

We use “dp” for density-independent pixels so that the design scales to the density of the user screen automatically. Save the file and switch back to the Graphical Layout to see the effect.

Graphical Layout Effect

The Graphical Layout is a useful reference tool while you design your layouts, but it is only a guide. To see how your layouts appear and function while your apps run, you have to load them onto either virtual or physical devices. We will look at this later on in this series.


5. Options

You can include a variety of layout types and Views to your app screens, but the basic process remains the same. We used a LinearLayout above, but there are many others. Among the most common are the RelativeLayout, FrameLayout, AbsoluteLayout, and GridLayout. You will find all these types in the Graphical Layout Palette so feel free to try some of them out and add a few Views of your choice to them. When you add elements from the Graphical Layout tool, switch to XML each time to see what markup code this produces.

The Android platform provides Views for many common purposes, like radio buttons, checkboxes, and text input fields. These save on the amount of functionality you implement manually, but if you need a UI element that is not provided, you can create a custom View class of your own. In general it’s best to do this only if you have no other option, as the standard UI elements are more reliable on user devices. They also save development and testing time.


Conclusion

In this tutorial we covered the basics necessary to design user interface layouts on Android, but we only scratched the surface of what’s possible. In the next part of this series, we will add some user interaction to the app, and detect and respond to clicks on the button we added. After that, we will look at the most relevant Java concepts we need to understand about Android before delving further into the various ingredients and practices involved in app development.


Corona SDK: Create a Shooter Game

$
0
0

In this tutorial, I’ll show you how to create a shooter game with limited bullets with the Corona SDK. The objective of the game is to shoot a high amount of targets with only five bullets. During this tutorial, you’ll work with timers, touch controls, and physics. To learn more, read on!

1. Application Overview

App Overview

Using supplied graphics we will code a shooting game using Lua and the Corona SDK API’s. In the game the player uses five bullets to shoot at his enemies. Each enemy will then create another four bullets that help take down a larger number of targets. While coding, you can modify the parameters in the code to customize your game.


2. Target Device

Target Device

Our first step is to select the platform we want to run our app in. This is important so that we can choose the size for our images.

The iOS platform has the following characteristics:

  • iPad 1/2/Mini: 1024x768px, 132 ppi
  • iPad Retina: 2048×1536, 264 ppi
  • iPhone/iPod Touch: 320x480px, 163 ppi
  • iPhone/iPod Retina: 960x640px, 326 ppi
  • iPhone 5/iPod Touch: 1136×640, 326 ppi

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

  • Asus Nexus 7 Tablet: 800x1280px, 216 ppi
  • Motorola Droid X: 854x480px, 228 ppi
  • Samsung Galaxy SIII: 720x1280px, 306 ppi

In this tutorial we’ll focus on the iOS platform with the graphic design, specifically to develop for distribution to an iPhone/iPod touch, but the code presented here applies to Android development with the Corona SDK as well.


3. Interface

Interface

We’ll use a simple interface with multiple shapes, buttons, and bitmaps. The interface graphic resources necessary for this tutorial can be found in the attached download.


4. Export Graphics

Export Graphics

Depending on the device you selected, you may need to export the graphics in the recommended ppi. You can do that in your favorite image editor. I used the Adjust Size… function in the Preview app on Mac OS X.

Remember to give the images a descriptive name and save them in your project folder.


5. App Configuration

An external file makes the application become full-screen across devices (the config.lua file). This file shows the original screen size and the method used to scale that content in case the app is run in a different screen resolution.

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

6. Main.lua

Now let’s write the application! Open your preferred Lua editor (any Text Editor will work, but you won’t have syntax highlighting) and prepare to write your new app. Remember to save the file as main.lua in your project folder.


7. Code Structure

We’ll structure our code as if it were a Class. If you know ActionScript or Java, you’ll find the structure familiar.

Necessary 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 hides the status bar. The status bar is the bar on top of the device screen that shows the time, signal, and other indicators.


9. Import Physics

We’ll use the Physics library to handle collisions. Use this code to import it:

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

10. Background

Background

The next line of code creates a simple background for the application interface.

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

11. Title View

Title View

This is the Title View; it will be 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

This view shows the credits and copyright of the game. This variable stores it:

-- [CreditsView]
local creditsView

13. Instructions Message

Instructions

An instructions message will appear at the start of the game and tween out after two seconds. You can change the time later in the code.

-- Instructions
local ins

14. Turret

Turret

This is the turret graphic, it will be placed at the center of our game.

-- Turret
local turret

15. Enemy

Enemy

Enemies appear from the edge of the screen, the next Group stores them.

-- Enemy
local enemies

16. Alert

Alert

This is the alert that’s displayed when the player runs out of bullets. It shows the score and ends the game.

-- Alert
local alertView

17. Sounds

Sounds

We’ll use sound effects to enhance the feeling of the game. The sounds used in this game were created in as3sfx and the background music is from PlayOnLoop.

-- Sounds
local bgMusic = audio.loadStream('POL-hard-corps-short.mp3')
local shootSnd = audio.loadSound('shoot.wav')
local exploSnd = audio.loadSound('explo.wav')

18. Variables

These are the variables we’ll use. You can read the comments in the code to learn more about them.

-- Variables
local timerSrc
local yPos = {58, 138, 218} --posible Y positions for enemies
local speed = 3
local targetX --stores position of enemy when shot
local targetY

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 createEnemy = {}
local shoot = {}
local update = {}
local onCollision = {}
local addExBullets = {}
local alert = {}

20. Constructor

Next we’ll create the function that initializes the game logic:

function Main()
	-- code...
end

21. Add Title View

Now we’ll place the TitleView in the stage and call a function that adds the tap listeners to the buttons.

function Main()
	titleBg = display.newImage('title.png')
	playBtn = display.newImage('playBtn.png', 212, 163)
	creditsBtn = display.newImage('creditsBtn.png', 191, 223)
	titleView = display.newGroup(titleBg, playBtn, creditsBtn)
	startButtonListeners('add')
end

22. Start Button Listeners

This function adds the necessary listeners to the TitleView 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 remove 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 credits screen is tapped, it’ll be tweened out of the stage and removed.

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 gets tapped the Title View is tweened and removed, revealing the Game View. There are many parts involved in this view so we’ll split them into the next few steps.

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 lines add the instructions message.

ins = display.newImage('ins.png', 135, 255)
	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. Bullets Left Indicator

This section adds the bullets at the top-left of the screen. It represents the available shots the player has left.

-- Bullets Left
	bullets = display.newGroup()
	bulletsLeft = display.newGroup()
	for i = 1, 5 do
		local b = display.newImage('bullet.png', i*12, 12)
		bulletsLeft:insert(b)
	end

28. Score TextField

This is the Score TextField created at the top-right of the stage:

-- TextFields
scoreTF = display.newText('0', 70, 23.5, 'Courier Bold', 16)
scoreTF:setTextColor(239, 175, 29)

29. Turret

Now we’ll place the turret in the stage.

-- Turret
	turret = display.newImage('turret.png', 220, 301)

30. Enemies Table & Background Music

Next we’ll create the enemies table, call a function that adds the game listeners, and start the background music.

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

31. Game Listeners

This function adds the necessary listeners to start the game logic:

function gameListeners(action)
	if(action == 'add') then
		timerSrc = timer.performWithDelay(1200, createEnemy, 0)
		Runtime:addEventListener('enterFrame', update)
	else
		timer.cancel(timerSrc)
		timerSrc = nil
		Runtime:removeEventListener('enterFrame', update)
		gameBg:removeEventListener('tap', shoot)
	end
end

32. Create Enemy

The following function creates the enemies. It starts by selecting a random Y position from the previously created table, then adds physics to the newly created object. We’ll add a collision listener to every enemy and also add them to the enemies table.

function createEnemy()
	local enemy
	local rnd = math.floor(math.random() * 4) + 1
	enemy = display.newImage('enemy.png', display.contentWidth, yPos[math.floor(math.random() * 3)+1])
	enemy.name = 'bad'
	-- Enemy physics
	physics.addBody(enemy)
	enemy.isSensor = true
	enemy:addEventListener('collision', onCollision)
	enemies:insert(enemy)
end

33. Shoot

When the player taps the screen a bullet is created and a sound plays. It has physics properties that detect collisions.

function shoot()
	audio.play(shootSnd)
	local b = display.newImage('bullet.png', turret.x, turret.y)
	physics.addBody(b)
	b.isSensor = true
	bullets:insert(b)

34. Update Bullets Left

Remove a bullet from the “Bullets Left” area at the top-left of the stage.

	-- Remove Bullets Left
	bulletsLeft:remove(bulletsLeft.numChildren)
	-- End game 4 seconds after last bullet
	if(bulletsLeft.numChildren == 0) then
		timer.performWithDelay(4000, alert, 1)
	end
end

35. Move Enemies

The following function runs every frame. Here we use it to move every enemy in the enemies table.

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

36. Move Shoot Bullets

A similar method is used for the bullets.

-- Move Shoot bullets
	if(bullets[1] ~= nil) then
		for i = 1, bullets.numChildren do
			bullets[i].y = bullets[i].y - speed*2
		end
	end

37. Move Explosion Bullets

When a bullet hits an enemy, four additional bullets form that move in four different ways. This code moves every bullet in the correct direction.

	-- Move Explosion Bullets
	if(exploBullets[1] ~= nil) then
		for j = 1, #exploBullets do
			if(exploBullets[j][1].y ~= nil) then exploBullets[j][1].y = exploBullets[j][1].y + speed*2 end
			if(exploBullets[j][2].y ~= nil) then exploBullets[j][2].y = exploBullets[j][2].y - speed*2 end
			if(exploBullets[j][3].x ~= nil) then exploBullets[j][3].x = exploBullets[j][3].x + speed*2 end
			if(exploBullets[j][4].x ~= nil) then exploBullets[j][4].x = exploBullets[j][4].x - speed*2 end
		end
	end
end

38. Collisions

This function runs when the bullet collides with an enemy. It plays a sound, calls the function that adds the four additional bullets, increases the score, and removes the objects implicated in the collision.

function onCollision(e)
	audio.play(exploSnd)
	targetX = e.target.x
	targetY = e.target.y
	timer.performWithDelay(100, addExBullets, 1)
	-- Remove Collision Objects
	display.remove(e.target)
	e.target = nil
	display.remove(e.other)
	e.other = nil
	-- Increase Score
	scoreTF.text = tostring(tonumber(scoreTF.text) + 50)
	scoreTF.x = 90
end

39. Add Explosion Bullets

This code creates and places the four additional bullets in the correct position to be moved by the update function.

function addExBullets()
	-- Explosion bullets
	local eb = {}
	local b1 = display.newImage('bullet.png', targetX, targetY)
	local b2 = display.newImage('bullet.png', targetX, targetY)
	local b3 = display.newImage('bullet.png', targetX, targetY)
	local b4 = display.newImage('bullet.png', targetX, targetY)
	physics.addBody(b1)
	b1.isSensor = true
	physics.addBody(b2)
	b2.isSensor = true
	physics.addBody(b3)
	b3.isSensor = true
	physics.addBody(b4)
	b4.isSensor = true
	table.insert(eb, b1)
	table.insert(eb, b2)
	table.insert(eb, b3)
	table.insert(eb, b4)
	table.insert(exploBullets, eb)
end

40. Alert

The alert function creates an alert view, animates it, and ends the game.

function alert()
	audio.stop(1)
	audio.dispose()
	bgMusic = nil
	gameListeners('rmv')
	alertView = display.newImage('alert.png', 160, 115)
	transition.from(alertView, {time = 300, xScale = 0.5, yScale = 0.5})
	local score = display.newText(scoreTF.text, (display.contentWidth * 0.5) - 18, (display.contentHeight * 0.5) + 5, 'Courier Bold', 18)
	score:setTextColor(44, 42, 49)
	-- Wait 100 ms to stop physics
	timer.performWithDelay(1000, function() physics.stop() end, 1)
end

41. Call Main Function

In order to begin the game, the Main function needs to be called. With the above code in place, we’ll do that here:

Main()

42. Loading Screen

Loading Screen

The Default.png file is an image that is displayed right when you start the application while the iOS loads the basic data to show the Main Screen. Add this image to your project source folder, it will automatically be added by the Corona compliler.


43. Icon

Icon

Using the graphics you created before, you can now create a nice-looking icon. The icon size for the non-retina iPhone icon is 57x57px, but the retina version is 114x114px and the iTunes store requires a 512x512px version. I suggest creating the 512×512 version first and then scaling down for the other sizes.

It doesn’t need to have rounded corners or transparent glare, iTunes and iPhone does that for you.


44. Testing in Simulator

Testing

It’s time for the final test! Open the Corona Simulator, browse to your project folder, and click “Open”. If everything works as expected, you are ready for the last step!


45. Build

Build

In the Corona Simulator go to File > Build and select your target device. Fill in the required data and click Build. Wait a few seconds and your app is ready for device testing and/or submission for distribution!


Conclusion

In this tutorial, we learned about physics, timers, touch listeners, and other skills that are useful in a wide variety of games. Experiment with the final result and try to make your custom version of the game!

I hope you enjoyed this series and found it helpful. Thank you for reading!

Tuts+ is Hiring a Mobile Dev Editor

$
0
0

We’re excited to announce that Tuts+ is currently looking for a mobile development expert to join our team. You’ll need to be someone with proven experience as a mobile developer, familiarity with the landscape of different platforms (iOS, Android, Windows Phone etc), excellent communication skills, and a passion for teaching.


What Does the Role Involve?

You’d be responsible for heading up all our mobile development tutorial and course content, managing a team of talented instructors, planning our content strategy, handling a budget, and teaching mobile development to our growing audience of millions. It’s a chance to be part of a global team that really cares about online education.

The role is a contract position, requires a commitment of between 20 and 40 hours a week (depending on the candidate), and gives you flexibility in scheduling your time.

We’re looking for someone who has:

  • Proven expertise in mobile development, and knowledge of multiple platforms (iOS, Android, Windows Phone etc)
  • Excellent written communication skills.
  • Good relationships and connections with other mobile developers in the industry.
  • Some experience with screencasting and online video content.
  • A long history of self-driven productivity and superior time management.
  • A passion for online learning and the potential life-changing effects of its outcomes.
  • A personable warmth, sense of humour and respect for individual team members.
  • A clear sense of fairness and a consistency of set expectations.
  • An attitude that aligns with Envato’s caring and passionate culture.

Interested?

If you’re interested in joining the team, we’d love to hear from you. You can read the full job advertisement at Tuts+ Jobs, and apply below:

If you’d like to have a role that pays you to stay at the cutting edge of the mobile dev industry, allows you to teach millions of people every month, and gives you the flexibility to work remotely, this might just be for you.

Android SDK: User Interaction

$
0
0

In this series we are learning about Android SDK development from scratch! In the last part, we created a basic user interface design with some typical Android elements. In this section, we’ll incorporate user interaction with the interface elements into the app.


Introduction

In this tutorial, we will detect and respond to user clicks on the Button element that we previously added. This involves a little Java programming within our app’s main Activity class. Don’t worry if you don’t have much experience with Java, just follow the steps below. We will look more at Java syntax in the next section, to make sure you know everything you need to about the language to carry out initial Android development tasks.

You can handle user interaction a few different ways with Android. We will look at two typical approaches to detect user clicks on buttons, both of which involve adding a little XML code as well as implementing some Java processing. On Android there are several different interactive UI elements that can receive various kinds of user input. Your handling of this input must be tailored to the UI item in question, but the overall process remains roughly the same. We will use a button to start exploring user interaction on Android, since it is among the most simple and commonly used elements.


1. User Interaction Basics

Before we get into the details, let’s explain a few UI concepts for those who are new to app development. To make an app interactive, we want to detect user interaction with particular elements. As we saw last time, on Android these are Views, in this case they are Buttons. To do this, we need to “listen” for the user interacting with the View in question. Although Android primarily runs on touchscreen mobile devices, we still use some of the language developed for interaction on a computer. For example, you will see the term “click” used to mean either clicking with a mouse or touching/ tapping with the finger.

The user can interact with the app in many ways. They can tap, slide, and “long-press” items. When one of these occurs, this is called an “event”. Therefore we want to set the app to listen for particular events occurring on particular UI items. In this case, we’ll listen for clicks (or taps/ touches) on the Button.

We want to respond and listen for user events. To do this we will add code to the Java Activity class to listen and respond to the button clicks. This code executes whenever a click event occurs on the button. The same process applies to handling user interaction with any View type, although the method code varies for different event types (i.e. events other than clicks).


2. Identifying UI Elements

Step 1

In order to tell which View the user is interacting with, we need to identify each interactive View in the app. We only have one initially, but your future apps may have multiple types of interactive Views in them. To achieve this, we give any View we need to identify a unique ID attribute we can use throughout the app.

Open your main layout file in Eclipse and switch to the XML editing tab. Locate the code we added for the Button element. Add an ID to it using the following syntax:

android:id="@+id/myButton"

You need ID attributes on many of the elements you use in Android layouts, since they allow you to identify Views uniquely. Notice the “@+id” syntax. This prompts the Android tools to create a new ID in the project resources “R.java” file, specifying a text string which must also be unique within the app, in this case “myButton”. In other parts of the XML layout code and in other XML and Java files in the app, we will use this name to specify the Button View. Save your layout file.

Step 2

Open your app’s main Activity file. We’re going to add a little bit of Java code, but don’t worry too much if your Java isn’t up to scratch, just try to understand the basic process involved in handling user interaction. If you are new to Java, when you work through the next tutorial you can refer back to this one to understand it fully. We’re going to create a variable in the class to refer to the Button View. At the top of the class declaration, after the opening line:

public class MainActivity extends Activity {

Add the variable declaration:

private Button theButton;

We declare the visibility (more details on this next time), the variable type, and the name. Eclipse may underline the “Button” text with the error message “Button cannot be resolved to a type”. We are using the Button type provided by the Android platform, so we must import this into the class file. Hover your mouse over the “Button” text and Eclipse will prompt you with a list of suggestions. Select “Import ‘Button’ (android.widget)”. This adds to the list of import statements you can expand and collapse near the top of the class file.

Import Prompt

Step 3

Now we can retrieve a reference to the Button View in the layout, storing this reference in the variable we created. In your Activity onCreate method, after the following line in which we set the layout:

setContentView(R.layout.activity_main);

Enter a new line to retrieve the Button as follows:

theButton = (Button)findViewById();

Inside the brackets for “findViewById()” type “R.” – Eclipse will prompt you with a list of resource types. Choose “id”.

ID Resource Prompt

Type another period “.” – Eclipse will present a list of existing ID values. We have only added one so far. Select the ID name we gave the Button (“myButton”) from the list.

ID Name Prompt

You’ll use this procedure regularly when you need to refer to resources in your Java code. You should now have the following line:

theButton = (Button)findViewById(R.id.myButton);

This statement assigns the Button View reference to the new variable we created, identifying the View using its ID.


3. Listening for Events

Step 1

The Android system only detects events on Views when we ask it to. Therefore we need to assign a listener to the View. We can do this in a couple of different ways, but let’s keep it to one of the simplest: having the Activity class itself listen and respond to clicks. At the top of the class, extend the opening declaration line as follows.

public class MainActivity extends Activity implements OnClickListener {

Eclipse will alert you to the “OnClickListener” type as before. Hover over the error and select an import as you did before, choose “Import ‘OnClickListener’ (android.view.View)”. Here you can see how Eclipse helps you to manage the ingredients in your project. It now displays another error message telling us we have to implement a method. We’ll resolve this next.

The “implements OnClickListener” code says that the Activity class is going to implement a particular interface. We will look at this practice in more detail next time – it essentially means that the class is going to provide functionality of a specific kind, in this case the functionality that allows us to handle clicks.

Step 2

Move back to the Activity onCreate method. After the line in which you assigned the Button View reference to the variable using its ID, add the following line:

theButton.setOnClickListener(this);

This line instructs the app to listen for clicks on the Button. The “this” in the brackets specifies the object that handles the clicks. In this case, it is the running instance of the Activity class itself.


4. Responding to Events

Step 1

Now we can respond to the button clicks. After the class onCreate method closing bracket:

theButton.setOnClickListener(this);
}

Add the following method outline:

public void onClick(View v){
		//respond to click
}

Carry out the import process again, hovering over “View” and selecting “Import ‘View’ (android.view)”. Since we instructed the class to listen for clicks on the button, when a click on it does occur, the content of this method will execute (the content, or “method body”, will be placed between the opening and closing curly brackets). The “View v” is a parameter to the method, this means that the method receives a reference to the clicked View, so we can identify it.

Step 2

Inside the onClick method, we first need to check which View was clicked. We only have one setup for click listening, but the app may later handle clicks on multiple Views. In the method body, check to see if the passed View parameter is the button we have a reference to in the variable we created:

if(v.getId()==theButton.getId()){
	//the button was clicked
}

This is a conditional statement (a structure we will cover in more detail next time) that checks the clicked View ID against the one we have a variable for. If the content of this block executes, we know the button we setup listening for was clicked. All of this testing may seem unnecessary when we only have one interactive element, but as you can imagine, when you have more than one clickable element you need to determine which one was clicked when onClick executes.

Step 3

Inside the if conditional block in onClick we can now respond to the button click. The response depends on the purpose of the button in a real app, but in this case we are demonstrating the process. Add the following code:

theButton.setText("Ouch");

Here we simply alter the text displayed on the button when it is clicked. Your onClick method should now appear as follows:

public void onClick(View v){
	//respond to click
	if(v.getId()==theButton.getId()){
		//the button was clicked
		theButton.setText("Ouch");
	}
}

Below is the result on a virtual device after clicking the button. We’ll cover running your apps on actual and virtual devices later on, so you can see the results in action!

Click Result on AVD

5. Alternatives & Options

Step 1

We demonstrated one way to handle button clicks on Android, but there are others. An alternative worth noting is to add the following attribute to your Button in the XML layout:

android:onClick="buttonClicked"

This specifies the name of a method to execute when the button is clicked. This method should be added to the Activity class displaying the layout. This removes the need for almost all of the code you added to the Activity class, including creating the Button variable, storing the View reference in it, implementing OnClickListener, and setting the class as click listener for the button. In this case, instead of adding the onClick method to the class, you can add the following (with equivalent code in it to produce the same effect):

public void buttonClicked(View v){
	Button theButton = (Button)v;
	theButton.setText("Ouch");
}

While this may seem simpler, the process of retrieving references to layout elements in Java is worth getting to know as you’ll find yourself doing so often. Also if your layout has multiple clickable items in it, you may prefer to handle all of the click events in one method, which you can do using the first approach outlined above.

There are other ways to handle clicks on Views beyond the two we have explored here, but these are the simplest, and are therefore advisable for your first projects.

Step 2

In this tutorial we worked through the basic process of handling button clicks on Android. The platform offers a range of other user event types for different Views, including long clicks, key presses, and touch events. See the Developer Guide for an overview of the possibilities you can try out in your future projects.


Conclusion

In this part, we explored the basic process to follow when you want to respond to user clicks on buttons in your Android UI. There is more to user interaction on Android than what we touched on here, but you should now have a grasp of the generic approach to handle the user input that many of your first projects will conform to. You can use what we learned in this section as a foundation to build your Android UI skills on. In the next tutorial, we will run through the most essential features of the Java language you need familiarity with in order to successfully learn Android development.

iOS 7 SDK: Core Bluetooth – Theoretical Overview

$
0
0

The Core Bluetooth (CB) framework provides the necessary resources for iOS apps to communicate with devices that are equipped with Bluetooth Low Energy technology (BTLE). This tutorial will guide you through the evolution of CB from iOS 5 to iOS 7. Additionally, you will learn how to configure a Core Bluetooth central and peripheral, how to communicate between them, and some best programming practices.


Introduction

The Core Bluetooth tutorials are divided into two sections. The first one covers the theoretical aspect of Core Bluetooth, while the second serves as a complete practical lesson. Here you will find the complete source code for the practical tutorial, plus an additional starting project.


1. Background

BTLE is based on the Bluetooth 4.0 specification, which among other things, defines a set of protocols for communicating between low energy devices. In BTLE there are two profiles:

  • The central: typically defines the logic behind a CB communication. It is able to scan, connect, and disconnect peripherals. Plus, it consumes the information available at each peripheral.
  • Peripheral: a device that has important information to share (heart rate, temperature, etc). The information can be pushed or advertised over the air.

The following image shows a central and a peripheral device:

iOS_CB_Image1
Illustration of central and peripheral devices.

Each “profile” represents an equivalent iOS object, namely the CBCentralManager and the CBPeripheral.

As stated earlier, the CBCentralManager manages discovered or connected remote peripheral devices (CBPeripheral). As soon as the CBCentralManager connects to a peripheral, interaction with its data begins. Data stored in peripherals are organized in a hierarchical tree based on its services and characteristics.

These services can be Alert Notification Service, Blood Pressure, Heart Rate, etc. The official list of GATT services specifications can be found on this page.

The characteristic of a service in practice is the service value. In this tutorial, the Blood Pressure service is the blood pressure value at a specific moment. The next figure illustrates a custom peripheral with one service and two characteristics.

iOS_CB_Image2
Illustration of a custom peripheral with one service and two characteristics.

In Core Bluetooth, the services of a remote peripheral are represented by CBService objects. Similarly, the characteristics of a remote peripherals service are represented by CBCharacteristic objects. The next figure illustrates the hierarchical structure of a CBService peripheral.

iOS_CB_Image3
Illustration of a peripheral services.

A given peripheral can have multiple services and multiple characteristics for each service. There is not a specific limit number for each one.

Note that you should read and learn the official Core Bluetooth Framework Reference to achieve a complete understanding of this technology.


2. Core Bluetooth Evolution

The Core Bluetooth Framework appeared in iOS 5 and introduced a new way to communicate between devices using Bluetooth wireless technology. During each iOS release, Apple improves and adds new features to Core Bluetooth.

In iOS 5, the main Core Bluetooth features were the CBCentralManager, CBPeripheral, Central, Client, and Observer. In this version only two classes existed, the CBCentralManager and CBPeripheral. The first class was designed to discover and connect to several (limited) peripherals. The second class was responsible for the visualization of a device and created a mechanism that enabled the Central to access data available on remote services.

In iOS 6, Apple introduced several Core Bluetooth features and improvements including CBPeripheralManager, Peripheral Database Caching, Broadcaster, Peripheral, and Server. The principal feature was the Server role. It permitted developers to create and specify custom services. In addition, the CBPeripheralManager introduced a customized way to create services and mechanisms that define how information is advertised to the network. Additionally, peripheral database caching greatly improved the general Bluetooth performance (especially in the discovery phase).

After a few years of gathering feedback, Apple refined the Bluetooth framework in iOS 7 with the following features:

  • Simpler device management
  • Smarter peripherals
  • Performance improvements
  • Application persistence
  • Built-in services
  • State preservation and restoration
  • Database caching evolved and now supports services, characteristics, and descriptors (previously only stored services and characteristics).
  • For sending data, the amount of data transmitted also changed. It is now possible to support MTU exchange requests and change the maximum amount of data per PDU.
  • iBeacon is a technology that permits the users to check the location and proximity of a specific device and the user’s iOS device.
  • Apple notification center service (ANCS) is an Apple-specific GATT service that exposes the characteristics necessary for accessories to be alerted for any notification events on the iOS device (notifications arriving, being modified, or dismissed) and to get more information about those events. Through this service, external accessory developers have full access to device events. However, the current version supports reading notification data only.

If you want to start playing with BTLE development, you must bear in mind the following considerations:

  • Note that Apple is decreasing iOS simulator support for Core Bluetooth. Thus, the best way to test your code is to run it directly on a iOS device.
  • You need an iOS device with hardware support for Bluetooth 4.0. All devices released since the iPhone 4S (including the 4S) support Bluetooth 4.0.
  • Your app can talk to a BTLE peripheral (this can be a second iOS device or a Mac).

3. CB Background Processing

Defining how an app reacts to a background or foreground state is crucial. Every app must behave differently in both background and foreground because system resources are limited. By default, many of the common CB tasks (on both the central and peripheral) are disabled while your app is in the background or in a suspended state. However, you can declare your app to support the Core Bluetooth background execution modes to allow it to be woken up from a suspended state to process certain events.

Note that even if your app supports one or both of the CB background execution modes, it cannot run forever. At a given point, the system may need to terminate your app to free up memory for the current foreground app because iOS is sovereign in memory management. Notwithstanding, Core Bluetooth supports saving state information for central and peripheral manager objects and restoring that state at app launch time.

If your app does not support background activities, all Bluetooth events that occur when the app is in a suspended state are queued by the system and fired to the app when it comes to foreground state. These alerts can be defined when calling the connectPeripheral:options: method of the CBCentralManager class when a connection to peripheral is made. There are three types of alerts:

  • CBConnectPeripheralOptionNotifyOnConnectionKey when you want the system to display an alert for a given peripheral if the app is suspended when a successful connection is made.
  • CBConnectPeripheralOptionNotifyOnDisconnectionKey when you want the system to display a disconnection alert for a given peripheral if the app is suspended at the time of the disconnection.
  • CBConnectPeripheralOptionNotifyOnNotificationKey when you want the system to display an alert for all notifications received from a given peripheral if the app is suspended at the time.

On the other hand, if your application supports the background mode you need to declare it (UIBackgroundModes) in the property list (Info.plist) file. When your app declares it, the system wakes it up from a suspended state to allow it to handle Bluetooth events. This support is important for apps that interact with Bluetooth Low Energy devices that deliver data at regular intervals, such as a heart rate monitor. There are two background roles: one for central devices and one for peripherals.


4. Best Practices for a CBCentralManager

Despite the fact that the Core Bluetooth framework makes many of the central transactions transparent to your app, there are several options that you must consider when developing a Bluetooth app. Since you are dealing with Low Energy devices, you should remember that every operation drains energy from your Bluetooth device.

Therefore, you must take into consideration the following:

  • Device scanning: you should only scan for new devices when absolutely necessary. Minimizing radio usage is especially important when developing an iOS device because radio usage has an adverse effect on any iOS device battery life.
  • Multiple advertisements from the same device: remote peripheral devices may send out multiple advertising packets per second to announce their presence to listening centrals. Thus, you can use the scanForPeripheralsWithServices:options: method to prevent this so all advertisements from a specific device are treated as one. However, you can use the CBCentralManagerScanOptionAllowDuplicatesKey option if you want to receive multiple advertisements from the same device.
  • Extract the peripheral’s data wisely. A peripheral device may have many services and characteristics than you are interested in. You should look for and discover only the services and characteristics your app needs.
  • Subscribe or check the characteristics values. You can retrieve characteristics by using user input or doing so automatically when that characteristic changes. You should use one method accordingly.
  • Every time you know that a connection is not needed you should terminate it. Due to caching mechanisms you can quickly re-connect. Apple has a specific work flow when a central tries to reconnect to a device. The next image demonstrates that work flow:
iOS_CB_Image7
Illustration of Apple reconnection work flow.

5. Best Practices for a CBPeripheral

Similar to the CBCentralManager role, the CBPeripheral has some practices that should be followed in order to create an efficient Bluetooth app.

With regards to advertising, remember that when your app is in the foreground it can use up to 28 bytes of space in the initial advertisement data. Be aware that you should only advertise data that really matters, not only for performance issues but to keep the channel clean. Also, you should offer the user a way to advertise as desired, so that the user has a way to control the advertisement’s frequency.

Also when you configure your characteristics, you should enable them to support notifications. To achieve this, you must add the CBAttributePermissionsReadable property to the permissions in the CBMutableCharacteristic object.

Be aware that since Bluetooth is an emerging technology, more and more devices use it and try to sniff the network to access “free” data. Because of this, you should always require a paired connection to access the sensitive data of your peripheral.


Conclusion

After reading this tutorial, you should understand the Core Bluetooth framework specifications. In the next tutorial, you will learn how to program a CBCentralManager and CBPeripheral.

If you have any questions or comments, please leave them below!

Android SDK: Java Application Programming

$
0
0

Our goal in this series is to learn about Android SDK development. So far we explored the development tools, looked at the structure of an Android app project, started to create a user interface, and responded to user interaction. In this tutorial, we will look at the basic structures and concepts in Java that you need to know in order to start developing apps for Android.


Introduction

If you are already familiar with Java you can ignore this section. If you have limited or no familiarity with the language, then this tutorial will indicate what you need to learn in order to go any further with Android. This tutorial is not enough in itself to teach you Java from scratch, but will act as a primer to get you started. You should follow the tutorial with additional Java learning as necessary.

We won’t spend too long going over the details in this tutorial, but if you are struggling with any of the concepts check out the Oracle Java Tutorials. This is an extensive guide to the language that is accessible to beginners. Don’t be too alarmed if you feel a little overwhelmed by what we cover in this tutorial at first, it will make a lot more sense once you start implementing the structures in Android projects.


1. Java Syntax

Step 1

You already saw a little Java syntax in our Android project, but for clarity, let’s start another project. Rather than an Android project, this time we will use a Java one, so that you can easily see the structures we use. Open Eclipse. Click the “New” button. In the wizard that appears, scroll down to the Java folder and expand it. Select “Java Project” and click “Next”.

Java Project

Enter “MyJavaProject” as the project name and click “Finish”. Eclipse then creates your new project in the workspace. In the Package Explorer, expand the new project folder. Right-click on “src” and select “New” then “Class”. Enter “MyMainClass” in the Name field. Check the checkbox with “public static void main” next to it and click “Finish”.

Java Class

Eclipse creates your class and opens it in the editor. Don’t pay much attention to the structure of the project or the existing content of the class because your Android projects will be differently structured. You can use this project to work on your Java coding skills, it’s easier to run and test the code you write here than with an Android app, and you can focus on the Java syntax.

The “public static void main” line you see in the class file is the main method. Whatever is inside this method executes when the application runs. The content of the method is what appears between the curly brackets after “public static void main(String[] args)”. Eclipse may have generated a “to do” line – just ignore it. Create a new line after it and we will add our code there.

Step 2

In Java, a variable can store a data value such as a text string or number. When you create, or “declare” a variable in Java, you have to specify the type of the data within it and give it a name. Enter the following:

int myNum;

This line declares an integer variable. We can declare a variable and assign a value to it by extending the line:

int myNum = 5;

We can now refer to this variable using its name. Add the following line next, writing the variable value to the output console:

System.out.println(myNum);

You will not typically write to the system output like this in your Android apps, but will use the LogCat view instead. However, writing to the output in this way is a convenient way to test your Java code.

Step 3

Let’s run the application. The process is slightly different for Android apps, but we’ll get to that later in the series. Select “Run” then “Run Configurations”. Select “Java Application” in the list on the left and click the “New launch configuration” button above it. Eclipse automatically selects your new Java application if it is the only one you have. Otherwise, select it using the “Browse” button.

Java Run Configuration

Click “Run” to run your application. You should see the number five written out to the Console view beneath the editor. You can use this technique to test your Java code as you learn it.

Console Output

You can run the project you ran last at any time using the “Run” button in the toolbar.

Run Button

Step 4

You’ll use the same syntax whenever you declare a variable in Java. To assign a different value to the variable later in the program, you can refer to it by name:

myNum = 3;

This overwrites the existing value. In Java there are many different variable types. The int is referred to as a primitive type, along with a few other number types, char for character values and boolean, which stores either a true or false value. There are also Object types; we will explore Objects later. An essential Object type to familiarize yourself with is String, which stores a text string:

String myName = "Sue";

Text string values are enclosed in quotes. You can include these directly in some cases, for example:

System.out.println("number: " + myNum);

Add this code and run it, the console will display: “number: ” followed by the variable value.

Step 5

Above we saw the assignment operator “=” – here are a few of the other common operators:

//add
myNum = 5+6;
//subtract
myNum = 7-3;
//multiply
myNum = 3*2;
//divide
myNum = 10/5;
//remainder
myNum = 10%6;
//increment (add one)
myNum++;
//decrement (subtract one)
myNum--;

The operators can be used on variables as well as hard-coded numbers (as above):

int myNum = 5;
int myOtherNum = 4;
int total = myNum+myOtherNum;//9

Step 6

One other Java structure that is essential to Android is the comment. You can add a comment in two ways:

//this is a single line comment
/* This is a multiline comment
* stretching across lines
* to give more information
*/

It is vital to get into the habit of commenting your code as you write it, for your own benefit as well as anyone else who reads the code.


2. Control Structures

Step 1

The code we added to the main method executes when the Java application runs. When the Android application we created runs, whatever is in the onCreate method of the main Activity is what runs. Each line inside these methods is executed after the previous line, but the flow of execution is not always linear. There are many control structures involved in Java, so let’s look at some of the most common, starting with conditionals.

Conditional statements involve carrying out tests to determine the flow of execution. The simplest conditional structure in Java is the if statement:

if(myNum>3)
	System.out.println("number is greater than 3");

This tests determines whether the value of the variable is greater than three. If it is, the string will be written to output. If not, then nothing will be written out and processing simply moves to the next line in the program. We say that a conditional test “returns” a true or false value. True and false are boolean values. We can add an else, which only executes if the if returned false:

if(myNum>3)
	System.out.println("number is greater than 3");
else
	System.out.println("number is not greater than 3");

The else executes if the value is three or less. Try the code with different values for the integer variable to see the results of the conditional tests. We can also chain multiple tests:

if(myNum>10)
	System.out.println("number is greater than 10");
else if(myNum>7)
	System.out.println("number is greater than 7");
else if(myNum>3)
	System.out.println("number is greater than 3");
else
	System.out.println("number is 3 or less");

Each test performs only if all previous tests in the chain returned false. So for any number, only one string is output. You can chain as many else if statements together as you need. You can also use if statements chained with one or more else if blocks without a final else.

We tested for one number being greater than another. Try the following variations:

if(myNum<10)
	System.out.println("number less than 10");
if(myNum==10)
	System.out.println("number equals 10");
if(myNum!=10)
	System.out.println("number is not equal to 10");
if(myNum>=10)
	System.out.println("number either greater than or equal to 10");
if(myNum<=10)
	System.out.println("number either less than or equal to 10");

You can carry out similar tests on other variable types including strings. To carry out multiple tests at once, use the following syntax:

if(myNum>=10 && myNum<=50)
	System.out.println("number is between 10 and 50");

The “&&”, known as the “and” operator, means that the whole statement will only return true if both tests return true. The “or” operator will return true if either test returns true:

if(myNum<0 || myNum!=-1)
	System.out.println("number is less than 0 or not equal to -1");

To group code into a block, we can use curly brackets – all of the code between the brackets executes if this test returns true:

if(myNum<10)
{
	System.out.println("number less than 10");
	myNum=10;
}

Such brackets group code in loops, methods, and classes.

Step 2

Let’s look at loops now. The following for loop iterates ten times, meaning its content executes ten times:

for(int i=0; i<10; i++){
	System.out.println(i);
}

The first expression in the for outline initializes a counter integer variable to zero. The second expression is a conditional test, checking that the variable is less than ten. If this returns true, the content of the loop executes, if not the loop will end. Once the content of the loop has executed, the third expression executes, incrementing the counter.

The while loop uses slightly different syntax. The following example has the same effect as the for loop:

int i=0;
while(i<10){
	System.out.println(i);
	i++;
}

Loops can contain multiple lines of code, including other loops.

Step 3

We have already encountered the main method and the Android onCreate method. Let’s look at creating your own methods. Place the following method after the closing bracket for your main method:

public static void doSomething(){
	System.out.println("something");
}

This method is defined as public, meaning any class in the project can call on its processing. If it was “private” it’s only accessible inside the class (this is “visibility”). You will not typically have to include the “static” modifier in your first Android apps, so ignore it. The “void” represents the return type. In this case the method returns nothing. To execute the method, add a call to it back in your main method:

doSomething();

Run your application to see this function. Alter the method to return a value:

public static int doSomething(){
	return 5;
}

Alter the method call and run again:

System.out.println(doSomething());

The returned value is written out. Methods can also receive parameters:

public static int doSomething(int firstNum, int secondNum){
	return firstNum*secondNum;
}

When calling the method, you must pass parameters of the correct type and number:

System.out.println(doSomething(3, 5));

Methods can split application processing into logical chunks. They are particularly useful if you need to carry out the same tasks more than once; you simply define them in the method then call it whenever you need it. If you change the process, you only need to change it in the method code.


3. Classes and Objects

Step 1

We’ve seen how methods can be used to reuse code and to split it into logical sections. Classes and objects do this on a larger scale. You can divide the tasks in an application up between objects, with each object having a set of responsibilities defined by its class. This is similar to a method being responsible for a particular area of functionality, but an object can have multiple methods and also store data values.

Imagine you are creating a game – you can create a class dedicated to handling the details of the user. Select your application package, in “src”, in the Package Explorer. Right-click and choose “New” then “Class”. Enter “GameUser” as the class name, make sure the main method stub checkbox is unchecked this time and click “Finish”. Eclipse then opens the class file, which initially only has the class declaration outline in it:

public class GameUser {
//class content
}

Everything you add is between these brackets (unless you add import statements, which are listed above this section). Your Android apps notice that the class files lists the package name at the top. It isn’t listed here because we used the default package.

Step 2

Inside the class, add a couple of variables:

private String playerName;
private int score;

These are called “instance variables” because they are defined for each instance of the class we create. Add a constructor method after these. This is what executes when an object of the class is created:

public GameUser(String userName, int userScore){
	playerName=userName;
	score=userScore;
}

The constructor always has the same name as the class and may or may not require parameters. The constructor should typically assign values to the instance variables, often using the parameters.

Step 3

The class can also define methods. Add the following typical set after the constructor:

public String getName() {return playerName;}
public int getScore() {return score;}
public void setName(String newName) {playerName=newName;}
public void setScore(int newScore) {score=newScore;}

These are known as get and set methods, or getters and setters, because they provide code external to the class with the ability to retrieve and set the values of the instance variables. Have a look at the Outline view in Eclipse to see how it can help to navigate class content.

New Class Outline

Step 4

Save your new class file. Back in your main class, create an object of the new class in the main method:

GameUser aUser = new GameUser("Jim", 0);

We pass the parameters listed in the constructor – the “new” keyword will make the constructor execute. We can now use this instance of the class to access the data values in it by calling its methods:

System.out.println(aUser.getScore());
aUser.setScore(5);
System.out.println(aUser.getScore());

Run the program to see how the value changes after calling the public methods on the object. You can create multiple instances of the object which will be managed separately:

GameUser anotherUser = new GameUser("Jane", 5);

4. Inheritance & Interfaces

Step 1

We’ve seen how a class defines the sets of responsibilities you can make use of by creating object instances. This applies not only to classes you create yourself, but also to existing Java and Android classes which you can also make use of. As well as creating instances of these platform classes, you can extend them using inheritance. With inheritance, you can create a class which inherits the functionality of an existing class while also providing its own processing. We saw an example of this in the first Android project we created, with the main Activity class.

Open the class now. In the opening line of the class declaration you will see “extends Activity”. This means that the class is a subclass of the Android Activity class. Using the Activity class lets Android handle the details of presenting a screen to the user, with methods for when the screen is in various states (created, paused, destroyed, etc). This lets you focus on the unique aspects of the app, by adding code to the methods defined within the Android Activity class declaration and additional methods of your own if necessary.

This is a pattern you will often use on Android, extending defined classes for common aspects of apps. You can complement these with your own classes where appropriate.

Step 2

Look again at your Activity class opening line. Remember that we added “implements OnClickListener” to handle clicks on a button in the UI. This is referred to as implementing an Interface. An Interface is similar to a class you inherit from using “extends” except that the Interface declaration simply lists method outlines. You have to provide the method implementation for each of them. So when we implemented OnClickListener we committed the class to providing an onClick method, which we did. An Interface is therefore like a contract. With inheritance, extending classes inherits the method implementations provided in the class declaration for their superclass (the class being extended). You can override these implementations if you need to.


Conclusion

In this tutorial we outlined some of the essential features of Java syntax you need to understand. There are more structures and concepts to become familiar with. If you don’t have Java experience and want to make sure you know enough to develop effectively for Android, use the Oracle Java Tutorials. Topics to consider learning about include arrays and switch statements. Later in the series we will look at some of the most common Android classes you are likely to use. In the next part, we will explore the resources in an Android app project.

iOS 7 SDK: Core Bluetooth – Practical Lesson

$
0
0

The Core Bluetooth (CB) framework provides the resources your iOS apps need to communicate with devices that are equipped with Bluetooth low energy (BTLE) technology. This tutorial will guide you through the evolution of CB from iOS 5 to iOS 7. Additionally, you will learn how to configure a Core Bluetooth central and peripheral, how to communicate between them, and inherent best programming practices when working with CB.


Introduction

The Core Bluetooth tutorials are divided in two parts. The first one covers the theoretical aspect of Core Bluetooth, while this tutorial is a complete practical lesson. You will find the complete source code attached to this post.


1. Download the Sample Source Code

This tutorial’s objective is to teach you how to use the Core Bluetooth framework. We prepared a sample source code that will make your life easier, and bypass the project creation and views configuration. You should download the sample code at the beginning of this page.

We assume that you know the basics of Xcode and iOS since we will only focus on the Core Bluetooth data. The sample code contains the following:

  • An application that uses the navigation controller, three views, and the inherent controllers.
  • The initial view controller ViewController with two buttons
  • A CBCentralManagerViewController that creates a custom iBeacon
  • A CBPeripheralViewController that receives the iBeacon and inherent information
  • A SERVICES header file with some variables to use across the app.

All views are already in place and properly defined. You just need to add the code for the Core Bluetooth process. Open the project, run it, and play with the objects to familiarize yourself with the code.

The SERVICES.h file contains two unique UUIDs. Those were generated using the terminal command uuidgen. You should generate them to your app, or you can use them.

Note that this lesson needs two iOS devices to work properly. Run the project and you’ll see an interface similar to this:

iOS_CB_Image4
Illustration of the CB interface

2. Programming a Central Role

In this tutorial, you will center the CBCentralManagerViewController class. The first step is to add the two protocols that support the CBCentralManager and CBPeripheral. The declaration of those protocols define methods (more on that later). Your interface should be like this:

@interface CBCentralManagerViewController : UIViewController < CBCentralManagerDelegate, CBPeripheralDelegate>

Now, you must define three properties: CBCentralManager, CBPeripheral, and NSMutableData. The first two are obvious, and the last one is used to store information that is shared between devices.

@property (strong, nonatomic) CBCentralManager *centralManager;
@property (strong, nonatomic) CBPeripheral *discoveredPeripheral;
@property (strong, nonatomic) NSMutableData *data;

At this point, you can swap to the implementation file. You will see a warning, but before solving that, you should initiate the centralManger and the data objects. You should start the centralManager with a self delegate and without any queue. You should use the viewDidLoad method and the result should be similar to this:

    _centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
    _data = [[NSMutableData alloc] init];

To resolve the warning issue you must add the - (void)centralManagerDidUpdateState:(CBCentralManager *)central method.

It is a required protocol method. It checks the state of the device and acts accordingly. There are several possible states and in your application you should always check for them. The states are:

  • CBCentralManagerStateUnknown
  • CBCentralManagerStateResetting
  • CBCentralManagerStateUnsupported
  • CBCentralManagerStateUnauthorized
  • CBCentralManagerStatePoweredOff
  • CBCentralManagerStatePoweredOn

For instance, if you run this application in a non Bluetooth 4.0 device you will get the CBCentralManagerStateUnsupported code. Here you will go for the CBCentralManagerStatePoweredOn and when it occurs you will start scanning for devices. For that, use the scanForPeripheralsWithServices method. If you pass nil as the first argument, the CBCentralManager starts to look for any service. Here you will use the UUID stored in the SERVICES.h.

The complete method is:

- (void)centralManagerDidUpdateState:(CBCentralManager *)central {
    // You should test all scenarios
    if (central.state != CBCentralManagerStatePoweredOn) {
        return;
    }
    if (central.state == CBCentralManagerStatePoweredOn) {
        // Scan for devices
        [_centralManager scanForPeripheralsWithServices:@[[CBUUID UUIDWithString:TRANSFER_SERVICE_UUID]] options:@{ CBCentralManagerScanOptionAllowDuplicatesKey : @YES }];
        NSLog(@"Scanning started");
    }
}

At this moment, your app will look for other devices. But despite the fact that any or none are available, you will not get any information. We can fix that. You should add the - (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI method. It will be called whenever a device is discovered. However, you will program it to react only to peripherals that are advertising the TRANSFER_SERVICE_UUID.

Additionally, we will use the new cache system and store the device for future reference and faster communication. The complete source code is as follows:

- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI {
    NSLog(@"Discovered %@ at %@", peripheral.name, RSSI);
    if (_discoveredPeripheral != peripheral) {
        // Save a local copy of the peripheral, so CoreBluetooth doesn't get rid of it
        _discoveredPeripheral = peripheral;
        // And connect
        NSLog(@"Connecting to peripheral %@", peripheral);
        [_centralManager connectPeripheral:peripheral options:nil];
    }
}

The connection to that device can fail. We need to deal with that scenario using a specific method called: - (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error. Add it and inform the user about that error.

- (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error {
    NSLog(@"Failed to connect");
    [self cleanup];
}

You will notice a warning, since the cleanup method is not yet declared. Let’s declare it! At this point, you may find the method source code to be complicated. However, we will explain it later on. You should return to it at the end of the tutorial for a complete understanding.

This method cancels any subscriptions to a remote device (if there are any), or straight disconnects if not. It loops along the services, then the characteristics, and removes the binds to them. The complete method is:

- (void)cleanup {
    // See if we are subscribed to a characteristic on the peripheral
    if (_discoveredPeripheral.services != nil) {
        for (CBService *service in _discoveredPeripheral.services) {
            if (service.characteristics != nil) {
                for (CBCharacteristic *characteristic in service.characteristics) {
                    if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:TRANSFER_CHARACTERISTIC_UUID]]) {
                        if (characteristic.isNotifying) {
                            [_discoveredPeripheral setNotifyValue:NO forCharacteristic:characteristic];
                            return;
                        }
                    }
                }
            }
        }
    }
    [_centralManager cancelPeripheralConnection:_discoveredPeripheral];
}

Taking into consideration that we successfully connected to the device, we now need to discover the services and characteristics of it. You must declare the - (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral. After the connection is established, stop the scanning process. Then clear the data that we may have received. Then make sure you get the discovery callbacks, and finally search for services that match your UUID (TRANSFER_SERVICE_UUID). Here’s the code:

- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral {
    NSLog(@"Connected");
    [_centralManager stopScan];
    NSLog(@"Scanning stopped");
    [_data setLength:0];
    peripheral.delegate = self;
    [peripheral discoverServices:@[[CBUUID UUIDWithString:TRANSFER_SERVICE_UUID]]];
}

At this point, the peripheral starts to notify its delegate with several callbacks. One of that callbacks is the - (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error. It is used to discover the characteristics for a given service. Not that you should always check if that method returns an error. If no error is found, you should find the characteristics you need, in this case the TRANSFER_CHARACTERISTIC_UUID. Here is the complete method:

- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error {
    if (error) {
        [self cleanup];
        return;
    }
    for (CBService *service in peripheral.services) {
        [peripheral discoverCharacteristics:@[[CBUUID UUIDWithString:TRANSFER_CHARACTERISTIC_UUID]] forService:service];
    }
    // Discover other characteristics
}

At this point if everything is correct, the transfer characteristic was discovered. Once again, a delegate method is called: - (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error. Once this has been found, you want to subscribe to it, which lets your CBCentralManager receive the data of that peripheral.

Once again, you should deal with errors (if any). You can do a leap of faith and directly subscribe to the characteristic. However, you should loop through the characteristics array and check if the characteristic is the proper one. If it is, then subscribe to it. Once this is complete, you just need to wait for the data to come in (another method). The complete method is below.

- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error {
    if (error) {
        [self cleanup];
        return;
    }
    for (CBCharacteristic *characteristic in service.characteristics) {
        if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:TRANSFER_CHARACTERISTIC_UUID]]) {
            [peripheral setNotifyValue:YES forCharacteristic:characteristic];
        }
    }
}

Every time the peripheral sends new data, the peripheral delegate uses the - (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error method. The second argument contains the characteristic that you can read.

Initially, you will create a NSString to store the characteristic value. Then, you will check if the data received is complete or if more will be delivered. Simultaneously, you will update your textview as soon as new data is received. After all data is completed, you can disconnect from the characteristic and disconnect from the device (although you can stay connected).

Note that, after the incoming data you can either disconnect or wait for other data. This callback lets us know if more data has arrived via notification on the characteristic. The complete source is below:

- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error {
    if (error) {
        NSLog(@"Error");
        return;
    }
    NSString *stringFromData = [[NSString alloc] initWithData:characteristic.value encoding:NSUTF8StringEncoding];
    // Have we got everything we need?
    if ([stringFromData isEqualToString:@"EOM"]) {
        [_textview setText:[[NSString alloc] initWithData:self.data encoding:NSUTF8StringEncoding]];
        [peripheral setNotifyValue:NO forCharacteristic:characteristic];
        [_centralManager cancelPeripheralConnection:peripheral];
    }
    [_data appendData:characteristic.value];
}

Additionally, there is a method that ensures that the CBCentral knows when a notification state for a given characteristic changes. It is very important to track it in order to understand when a characteristic state changes (update app values). The method is: - (void)peripheral:(CBPeripheral *)peripheral didUpdateNotificationStateForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error. You should check if the characteristic notification has stopped. If it has, you should disconnect from it:

- (void)peripheral:(CBPeripheral *)peripheral didUpdateNotificationStateForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error {
    if (![characteristic.UUID isEqual:[CBUUID UUIDWithString:TRANSFER_CHARACTERISTIC_UUID]]) {
        return;
    }
    if (characteristic.isNotifying) {
        NSLog(@"Notification began on %@", characteristic);
    } else {
        // Notification has stopped
        [_centralManager cancelPeripheralConnection:peripheral];
    }
}

If the disconnection between devices occurs, you need to clean up your local copy of the peripheral. For that use the - (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error method. This method is simple and sets the peripheral to zero. Additionally, you can re-start the device scanning or leave the app (or another). In this example, you will re-start the scanning process.

- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error {
    _discoveredPeripheral = nil;
    [_centralManager scanForPeripheralsWithServices:@[[CBUUID UUIDWithString:TRANSFER_SERVICE_UUID]] options:@{ CBCentralManagerScanOptionAllowDuplicatesKey : @YES }];
}

Finally, one additional step is required. Every time the view disappears, you should stop the scanning process. In the viewWillDisappear:(BOOL)animated method you should add:

  [_centralManager stopScan];

You can Run the app, however you need the peripheral app to receive some data. The next image presents the final interface of the CBCentralManager.

iOS_CB_Image5
Illustration of the CBCentralManager.

3. Programming a Peripheral Role

In this tutorial, you will center the CBPeripheralViewController class. The first step is to add two protocols: CBPeripheralManagerDelegate and UITextViewDelegate. Your interface should now look like:

@interface CBPeripheralViewController : UIViewController < CBPeripheralManagerDelegate, UITextViewDelegate>

You must now define four properties: CBPeripheralManager, CBMutableCharacteristic, NSData, and NSInterger. The first two represent the peripheral manager and its characteristics, while the third is the data that will be sent. The last one represents the data index.

@property (strong, nonatomic) CBPeripheralManager *peripheralManager;
@property (strong, nonatomic) CBMutableCharacteristic *transferCharacteristic;
@property (strong, nonatomic) NSData *dataToSend;
@property (nonatomic, readwrite) NSInteger sendDataIndex;

Now switch to the implementation file. Our first step is to initiate the _peripheralManager and configure it to start advertising. The service advertisement should initiate with the aforementioned service UUID. Your viewDidLoad should look like this:

- (void)viewDidLoad {
    [super viewDidLoad];
    _peripheralManager = [[CBPeripheralManager alloc] initWithDelegate:self queue:nil];
    [_peripheralManager startAdvertising:@{ CBAdvertisementDataServiceUUIDsKey : @[[CBUUID UUIDWithString:TRANSFER_SERVICE_UUID]] }];
}

You should see a warning. To fix it, declare the - (void)peripheralManagerDidUpdateState:(CBPeripheralManager *)peripheral protocol method. Similar to CBCentralManager you should control and test all app states. If the state is CBPeripheralManagerStatePoweredOn you should build and define your service and characteristics (one of the true features of iOS 7).

Each service and characteristic must be identified by a unique UUID. Note that the third argument of the init method is at nothing. Doing so declares that the data to be exchanged will be defined later on. This is usually done when you want to create the data dynamically. If you want to have a static value to transmit, then you can declare it here.

The properties determines how the characteristic value can be used, and there are several possible values:

  • CBCharacteristicPropertyBroadcast
  • CBCharacteristicPropertyRead
  • CBCharacteristicPropertyWriteWithoutResponse
  • CBCharacteristicPropertyWrite
  • CBCharacteristicPropertyWrite
  • CBCharacteristicPropertyNotify
  • CBCharacteristicPropertyIndicate
  • CBCharacteristicPropertyAuthenticatedSignedWrites
  • CBCharacteristicPropertyExtendedProperties
  • CBCharacteristicPropertyNotifyEncryptionRequired
  • CBCharacteristicPropertyIndicateEncryptionRequired

For a complete understanding of those properties, you should check the CBCharacteristic Class Reference.

The last argument of the init is the read, write, and encryption permissions for an attribute. Again, there are several possible values:

  • CBAttributePermissionsReadable
  • CBAttributePermissionsWriteable
  • CBAttributePermissionsReadEncryptionRequired
  • CBAttributePermissionsWriteEncryptionRequired

After the characteristic defined it, it is now time to define the service using the CBMutableService. Note that the service must be defined with the TRANSFER_CHARACTERISTIC_UUID. Add the characteristic to the service and then add it to the peripheral manager. The complete method is below:

- (void)peripheralManagerDidUpdateState:(CBPeripheralManager *)peripheral {
    if (peripheral.state != CBPeripheralManagerStatePoweredOn) {
        return;
    }
    if (peripheral.state == CBPeripheralManagerStatePoweredOn) {
        self.transferCharacteristic = [[CBMutableCharacteristic alloc] initWithType:[CBUUID UUIDWithString:TRANSFER_CHARACTERISTIC_UUID] properties:CBCharacteristicPropertyNotify value:nil permissions:CBAttributePermissionsReadable];
        CBMutableService *transferService = [[CBMutableService alloc] initWithType:[CBUUID UUIDWithString:TRANSFER_SERVICE_UUID] primary:YES];
        transferService.characteristics = @[_transferCharacteristic];
        [_peripheralManager addService:transferService];
    }
}

Now that we have the service and its characteristics (one in this case), it is now time to detect when a device connects to this one and reacts accordingly. The - (void)peripheralManager:(CBPeripheralManager *)peripheral central:(CBCentral *)central didSubscribeToCharacteristic:(CBCharacteristic *)characteristic method catches when someone subscribes to our characteristic, then starts sending them data.

The app sends the data available at the textview. If the user changes it, the app sends it to them in real time to the central subscribed. The method calls a custom method called sendData.

- (void)peripheralManager:(CBPeripheralManager *)peripheral central:(CBCentral *)central didSubscribeToCharacteristic:(CBCharacteristic *)characteristic {
    _dataToSend = [_textView.text dataUsingEncoding:NSUTF8StringEncoding];
    _sendDataIndex = 0;
    [self sendData];
}

The sendData is the method that deals with all logic regarding the data transfer. It can do several actions such as:

  • Send data
  • Send the end of communication flag
  • Test if the app sent the data
  • Check if all data was sent
  • React to all of the previous topics

The complete source code is presented below. Several comments were left purposefully in order to facilitate its understanding.

- (void)sendData {
    static BOOL sendingEOM = NO;
    // end of message?
    if (sendingEOM) {
        BOOL didSend = [self.peripheralManager updateValue:[@"EOM" dataUsingEncoding:NSUTF8StringEncoding] forCharacteristic:self.transferCharacteristic onSubscribedCentrals:nil];
        if (didSend) {
            // It did, so mark it as sent
            sendingEOM = NO;
        }
        // didn't send, so we'll exit and wait for peripheralManagerIsReadyToUpdateSubscribers to call sendData again
        return;
    }
    // We're sending data
    // Is there any left to send?
    if (self.sendDataIndex >= self.dataToSend.length) {
        // No data left.  Do nothing
        return;
    }
    // There's data left, so send until the callback fails, or we're done.
    BOOL didSend = YES;
    while (didSend) {
        // Work out how big it should be
        NSInteger amountToSend = self.dataToSend.length - self.sendDataIndex;
        // Can't be longer than 20 bytes
        if (amountToSend > NOTIFY_MTU) amountToSend = NOTIFY_MTU;
        // Copy out the data we want
        NSData *chunk = [NSData dataWithBytes:self.dataToSend.bytes+self.sendDataIndex length:amountToSend];
        didSend = [self.peripheralManager updateValue:chunk forCharacteristic:self.transferCharacteristic onSubscribedCentrals:nil];
        // If it didn't work, drop out and wait for the callback
        if (!didSend) {
            return;
        }
        NSString *stringFromData = [[NSString alloc] initWithData:chunk encoding:NSUTF8StringEncoding];
        NSLog(@"Sent: %@", stringFromData);
        // It did send, so update our index
        self.sendDataIndex += amountToSend;
        // Was it the last one?
        if (self.sendDataIndex >= self.dataToSend.length) {
            // Set this so if the send fails, we'll send it next time
            sendingEOM = YES;
            BOOL eomSent = [self.peripheralManager updateValue:[@"EOM" dataUsingEncoding:NSUTF8StringEncoding] forCharacteristic:self.transferCharacteristic onSubscribedCentrals:nil];
            if (eomSent) {
                // It sent, we're all done
                sendingEOM = NO;
                NSLog(@"Sent: EOM");
            }
            return;
        }
    }
}

Finally, you must define a callback that is called when the PeripheralManager is ready to send the next chunk of data. This ensures that packets arrive in the order they are sent. The method is the - (void)peripheralManagerIsReadyToUpdateSubscribers:(CBPeripheralManager *)peripheral and it only calls the sendData method. The complete version is below:

- (void)peripheralManagerIsReadyToUpdateSubscribers:(CBPeripheralManager *)peripheral {
    [self sendData];
}

You can now finally Run the app and test the Bluetooth communication. The next image shows the interface of the CBCentralManager.

iOS_CB_Image6
Illustration of the Peripheral interface.

Conclusion

At the end of this tutorial, you should understand the Core Bluetooth framework specifications. You should also be able to define and configure a CBCentralManager and a CBPeripheral role, and understand and apply some best practices when developing with Core Bluetooth.

If you have any questions or comments, please leave them below!

Android SDK: App Resources

$
0
0

We are learning how to develop Android apps in this series. So far, we’ve looked at the structure of an Android app and explored user interfaces. In this tutorial, we will learn to work with the project resources.


Introduction

In this part of the series, we will examine the resource types you will most likely use in your first projects. Project resources include the layouts, images, and data values used within the app. When you create a new project, a few folders for common resource types are included in your project directory automatically. You can add folders for additional types should you need them.

You can find the resources for the project we created earlier in the series by browsing to the “res” folder in the Package Explorer. Expand the folder to see its contents. You can add new folders to the resources directory and can add new files to each one, as well as work with the existing files (as we did with the layout and strings values files earlier in this series).


1. Alternative Resources

Before we start with the specifics, it’s worth noting that you can place your Android resources into two categories: resources that can be used across devices and resources that are tailored to a subset of devices. You can see an example of this in the existing project structure. In the Eclipse Package Explorer, look at the “res” directory. Remember that the different drawable folders are tailored to specific device screen densities. We will add one in this tutorial for drawable files that are not targeted (ones that can be used across devices).

You can add alternative directories for each resource type using qualifiers to target categories, as Eclipse has done with “drawable-hdpi”, “drawable-xhdpi”, and so on. The Android platform supports such qualifiers for various aspects of the user device, including screen size, density, API level, language, region, and more. Any resource type folder that does not include a qualifier in the name is for resources that can be used across devices. You will not always need qualified folders for all of your resource types, but when you test your apps on different devices you may find that some aspects need tweaking to remain usable across configurations.


2. Drawables

Step 1

As we know, Eclipse creates multiple drawable folders, each targeted at a particular density bucket. The drawable folders contain any images you use in your app. You can include images prepared outside of Eclipse in digital formats, such as JPEG, PNG, and GIF. You can also define drawables in XML code. Let’s do this and add one to the main layout.

Although you should generally try to tailor your drawables to each target density, for the purposes of this tutorial we will use a single drawable for all devices. With the “res” folder selected in the Eclipse Package Explorer, create a new folder by choosing “File” or right-clicking the folder, then select “New” and “Folder”. Give the folder the name “drawable” and click “Finish” to create it.

New Folder

This is the process to follow any time you need to create a new folder in your project.

Step 2

Your new drawable folder should now appear in the Packager Explorer alongside the existing drawable folders. As we explored above, if a folder is not targeted to a particular subset of devices, e.g. defined using density categories or API levels (such as the values folders), you can place resources within in it that can be used on any user device. So whatever we place in the new drawable folder is displayed on all user devices. For most drawables you should prepare specific versions for different densities, but for simplicity we will use the new folder in this tutorial.

Create a new file in your new drawable folder by selecting it in the Package Explorer, right-clicking or choosing “File”, then choosing “New” and “Android XML File”. You will see a wizard to create the new file. Android supports a few different types of drawable files. We are going to create a shape drawable in which we define an image using markup to represent the different aspects of its shape and appearance. See the Developer Guide for an overview of the other drawable types.

New Shape File

In the top drop-down list you can choose the type of resource, which is automatically selected for drawable since we are creating the file in that folder. Next is the project drop-down list, which should also be automatically populated with the project you selected. Next is a text-field for the file-name – enter “nice_shape.xml”. Below that is a list of root elements you can choose. Scroll down and choose “shape” since we are going to define a shape drawable. Click “Finish”. Eclipse will create the new file and open it for editing.

Step 3

With a shape drawable, you can choose from a range of generic shape types, including rectangle, oval, line, and ring. Once you choose a shape type, you can then define properties of the shape including solid or gradient colors, corners, padding, dimensions, and strokes. Edit your root shape element to choose a rectangle:

<shape xmlns:android="http://schemas.android.com/apk/res/android"
	android:shape="rectangle" ></shape>

You can then define the shape properties by adding other elements inside the root shape element. Start by defining a gradient:

<shape xmlns:android="http://schemas.android.com/apk/res/android"
	android:shape="rectangle" ><gradient
		android:angle="270"
		android:centerColor="#FFFFFF00"
		android:endColor="#FF0000FF"
		android:startColor="#FFFF0000"
		android:type="linear" /></shape>

We define the gradient type, angle, and start, end, and center colors. After the gradient element, let’s add some rounded corners:

<corners android:radius="10dp" />

Next add a stroke:

<stroke
	android:width="2dp"
	android:color="#FF339966" />

When you type in the editor, you will see the available element and attribute types in the Eclipse prompts, so take some time to experiment with them after you complete this tutorial. We will use the shape in our UI in the next step. Save your drawable file for the moment.

Tip: To use digital image files you prepare outside Eclipse in your apps, simply copy them to the relevant drawable folders in your workspace directory. After copying files into the resource folders, you may have to refresh the Eclipse views. Do this in the Package Explorer by selecting the project, right-clicking or choosing “File”, then selecting “Refresh”. You will then be able to refer to the files in your application code.

3. Layouts

Step 1

We started looking at layouts earlier in the series, when we designed the app user interface. Let’s see how the layout file and drawables interact. We can display a drawable in the layout as the background of a View or within a dedicated View. Start by listing the shape drawable we created as background for an existing View. Open your app’s main layout file. Let’s set the shape drawable as background for the button we added. Add the following attribute to your Button element:

android:background="@drawable/nice_shape"

We use the resource type and name (the file-name we gave the drawable) to refer to it in the layout. Notice that this is the same syntax pattern we used when referring to string values. Save and switch to the Graphical Layout tab to see the shape as button background. You may notice that the button needs a little padding, so switch back to XML editing and add a padding attribute to the Button element:

android:padding="5dp"

Switch back to the Graphical Layout to see the effect.

Background Layout

Step 2

Now let’s use the shape drawable in a dedicated View. Add the following after the Button element in your layout:

<ImageView
	android:layout_width="fill_parent"
	android:layout_height="fill_parent"
	android:layout_margin="10dp"
	android:src="@drawable/nice_shape" />

We set the ImageView to fill the available space minus a margin. You can optionally set it to use a fixed width and height. Notice that Eclipse displays a warning because you have not added a content description attribute, this helps accessibility so let’s add one. Open your “res/values” strings XML file and add the following:

<string name="pic">Picture</string>

Now you can add the string to the ImageView in your layout file:

android:contentDescription="@string/pic"

As you can see, working with resources involves switching back and forth between various files in the project and using standard syntax patterns to make references between the resource items. Toggle again to view the graphical preview.

Image View

You can use the controls to zoom in and out.


4. Other Resource Types

So far we used three resource types in the app: layout, drawable, and values. There’s more you can use in your apps, using the same process we used above to reference them. As we saw earlier in the series, you can also reference resources in your Java files using the following syntax:

//R.type.name
R.string.pic//example

Let’s briefly summarize some of the other resource types you may find useful in future apps. We used drawable and layout resources above and in previous tutorials, and used string values in the layout file. Expand the “values” folder in the Package Explorer. Alongside the strings file, Eclipse typically adds one for dimensions and one for styles. In the styles file you can define coherent appearance properties for your app UIs. In the “dimens” file you can define dimension values you wish to use in your apps.

As we mentioned above, you can create alternative resource type folders using qualifiers for particular device properties. As you can see Eclipse creates values folders targeted at particular API levels, but you can target devices using many other qualifiers. For example, you may want to use fixed width and height for the ImageView we added, tailoring the displayed size to device screen size. To achieve this, you could add values folders for each size or density bucket (“-small”, “-large”, “-hdpi”, “-mdpi”, etc), with a dimensions file in each. By including a dimensions value in each of these files, giving the value the same name but a different number, Android automatically picks the correct one for the user device.

Other resource types you may find useful include those for numbers, menus, animation, and color values. Eclipse normally creates a menu folder when you create an app, so have a look in it now. To define XML animations, you can add an “anim” or “animator” folder to “res”, or add your animation files to the drawable folders depending on the type you use.

If you want to use a set of colors across your app UI, you can define them in a file saved in the values directory, using the color element. Each color element can contain a HEX value and a name attribute, so that you can refer to the color in your other files. XML resources that do not fall under one of the defined categories on Android can be saved in an “xml” directory in “res”.

For an overview of all of the resource types on Android, see the Developer Guide sections on Resource Types and More Resource Types. Although your needs will be fairly straightforward at first, it’s worth looking through the list now so that you have an idea of what’s possible later on.

Tip: When you look at Android examples or the Developer Guide, you will often see the same standard filenames being used for resources. However, the filenames are typically arbitrary – as long as you use the correct folder names and elements, your application code will access all of your resources using the identification system. That aside, sticking to conventional filenames can make your apps easier to work with, particularly in the values folders.

Conclusion

In this tutorial, we looked at the basics of app resources on Android. But as you have seen, there is much more to explore. For your first few apps you can keep things relatively simple as you get accustomed to the practice of using resources. But as your apps develop, you should try to think about the variety of user devices your apps may run on, providing additional resources as necessary. In the next part of the series, we will look at the project Manifest file.


iOS 7 SDK: iBeacons Game

$
0
0

This tutorial will guide you through the new iBeacons technology. In order to explain this technology in an interesting manner, you will create a “hot and cold” app in this tutorial. The app will analyze the beacon region and inform you accordingly.


Introduction

iBeacon is a technology introduced in iOS 7 that permits you to add precise location region monitoring to your application. Despite the fact that iBeacon is classified as a Core Location technology, iBeacon uses Bluetooth Low Energy technology.

iBeacons supports three types of distance profiles between the iBeacon and the device: immediate, near, and far. Through these distances, it is possible to track the device’s movement within the range of the iBeacon. iBeacons work in concert with specific region monitoring. An iOS application can be configured to verify a specific iBeacon signature, and when the iOS device comes within a proximity of that iBeacon, the application notifies the user.

In order to turn an iOS 7 device into an iBeacon, you must create an instance of CLBeaconRegion. It must be created with the UUID and Identifier properties. However, you can also declare and define two more (non-required) properties: Major Value and Minor Value.

Note that, the UUID is a unique iBeacon identifier. Thus, the UUID parameter should be unique to your application. If your application uses multiple devices as iBeacons they should all share the same UUID. In this case, you should configure the iBeacons by the proximity value, using the major and minor value, thus creating singular groups identifying each iBeacon.

Since you now know what a iBeacon is and its basic properties, we can implement an iBeacon. To successfully complete this tutorial, you need two iOS devices with Bluetooth 4.0 support (iPhone 4 or superior). One of devices creates and notifies the iBeacon, while the other receives the signal and presents information regarding the distance of that device to the iBeacon.

This is what our end result will look like:

iOS_iB_01
Illustration of the final result

1. Code Download

Since the objective of this tutorial is to teach you how to create and implement an iBeacon, we will provide you a sample code with several views and objects that are already defined. You can download the sample code at the beginning of this page.

Nevertheless, the sample code contains the following:

  • An application that uses the navigation controller and three views and controllers.
  • The initial view controller ViewController with two buttons (Send iBeacon and receive iBeacon My Proximity).
  • A SendViewController that creates a custom iBeacon.
  • A GetViewController that receives the iBeacon and presents the information regarding the distance to that iBeacon.

All views are already placed and properly defined. You just need to add the code for the iBeacon process. Open the project, run it, and play with the objects in order to familiarize yourself with the code. The following picture presents the image that you will see when you run the project the first time.

iOS_iB_01
Illustration of the main app interface

Note that as aforementioned, two frameworks are included:

#import &lt;CoreLocation/CoreLocation.h&gt;
#import &lt;CoreBluetooth/CoreBluetooth.h&gt;

If you want (or need) to, you can consult the official framework documentation of both CoreLocation and CoreBluetooth.


2. Create an iBeacon

Let’s get to work! Our first step is to focus on the SendViewController.h file. Here you will define the properties inherent to the iBeacon definition and the proper delegate.

You need three properties to create the iBeacon: a CLBeaconRegion, a CBPeripheralManager, and a NSDictionary. The CLBeaconRegion object defines a type of region that is based on the device’s proximity to a Bluetooth beacon. It looks for devices whose identifying information matches the information you provide. When that device comes in range, the region triggers the delivery of an appropriate notification. The CBPeripheralManager object manages published services within the local peripheral device’s Generic Attribute Profile (GATT) database and advertises these services to central devices. Finally, the NSDictionary stores the information that will later be advertised. That said, the following snippet will help you to create those properties:

@property (strong, nonatomic) CLBeaconRegion *beaconRegion;
@property (strong, nonatomic) NSDictionary *beaconPeripheralData;
@property (strong, nonatomic) CBPeripheralManager *peripheralManager;

In terms of the delegate, you will use the CBPeripheralManagerDelegate. This protocol is used by the delegate to verify publishing and advertising, and to monitor read, write, and subscription requests from remote central devices.

@interface SendViewController : ViewController &lt; CBPeripheralManagerDelegate&gt;

Save your project and change to the SendViewController.m file. One warning will be there waiting for you. Before you fix that problem, initialize and allocate resources for the previous properties. In the - (void)viewDidLoad method you should first start to initialize the beaconRegion using a unique UUID. The UUID can be generated using the Terminal.app and the command uuidgen.

Here, the _beaconRegion object is initialized using four properties (two required and two optional). Note that you can initialize it with three different methods (check the documentation). The first property is the unique UUID, the second and third are optional and are related with specifications inside the app (group and beacon inside group). The last property is the iBeacon identifier. The snippet is:

NSUUID *uuid = [[NSUUID alloc] initWithUUIDString:@&quot;F2037E44-13BF-4083-A3A6-514A17BBBA10&quot;];
_beaconRegion = [[CLBeaconRegion alloc] initWithProximityUUID:uuid major:1 minor:1 identifier:@&quot;com.MobileTuts.iBeacons&quot;];

In order to give some feedback to the user, update the label with the UUID generated before:

_uuidLabel.text = _beaconRegion.proximityUUID.UUIDString;

Now you need to initialize the two remaining class properties. The _beaconPeripheralData calls the _beaconregionperipheralDataWithMeasuredPower method that retrieves data that can be used to advertise the current device as a beacon. The _peripheralManager is initialized with the delegate to receive the peripheral role events, the dispatch queue for dispatching the peripheral role events, and an optional dictionary containing initialization options for a peripheral manager. Here’s the complete snippet:

_beaconPeripheralData = [_beaconRegion peripheralDataWithMeasuredPower:nil];
_peripheralManager = [[CBPeripheralManager alloc] initWithDelegate:self queue:nil options:nil];

At this point, you allocated the necessary resources, so you only need to fix the warning. Add the -(void)peripheralManagerDidUpdateState:(CBPeripheralManager *)peripheral delegate method. This method is used to check the device state, and taking into consideration the state, the app acts accordingly. In this case if the state is CBPeripheralManagerStatePoweredOn, the app will begin the advertisement. There are several available states. In a real application you should test them all. The states are:

  • CBCentralManagerStateUnknown
  • CBCentralManagerStateResetting
  • CBCentralManagerStateUnsupported
  • CBCentralManagerStateUnauthorized
  • CBCentralManagerStatePoweredOff
  • CBCentralManagerStatePoweredOn

Here is the complete method to implement:

-(void)peripheralManagerDidUpdateState:(CBPeripheralManager *)peripheral {
if (peripheral.state == CBPeripheralManagerStatePoweredOn) {
NSLog(@&quot;On&quot;);
[_peripheralManager startAdvertising:_beaconPeripheralData];
} else if (peripheral.state == CBPeripheralManagerStatePoweredOff) {
NSLog(@&quot;Off&quot;);
[_peripheralManager stopAdvertising];
}
}

At this time you have the iBeacon created and configured. You can now start the iBeacon advertisement. However, you need to implement a client app in order to try it out. The next step will guide you to achieve that. The following image presents the UI that you should see when you run the app.

iOS_iB_02
Illustration of the iBeacon

3. Receive an iBeacon

To change your view to the GetViewController.h class define two objects, one CLBeaconRegion and the other CLLocationManager. The CLBeaconRegion is similar to the aforementioned definition, and you should not have any difficulty in the creation process. The CLLocationManager defines the interface for configuring the delivery of location related events to your application.

@property (strong, nonatomic) CLBeaconRegion *beaconRegion;
@property (strong, nonatomic) CLLocationManager *locationManager;

Additionally, you need to define a protocol delegate, this time the CLLocationManagerDelegate.

@interface GetViewController : ViewController &lt;CLLocationManagerDelegate&gt;

Now move to the GetViewController.m and let’s allow and initialize the objects. The _locationManager is simple and you should set the delegate to self. Then you need to create a UUID and define the _beaconRegion. Additionally, you need to define a region for the monitoring. In this case you will monitor the _beaconRegion region.

_locationManager = [[CLLocationManager alloc] init];
_locationManager.delegate = self;
NSUUID *uuid = [[NSUUID alloc] initWithUUIDString:@&quot;F2037E44-13BF-4083-A3A6-514A17BBBA10&quot;];
_beaconRegion = [[CLBeaconRegion alloc] initWithProximityUUID:uuid identifier:@&quot;com.MobileTuts.iBeacons&quot;];
[_locationManager startMonitoringForRegion:_beaconRegion];

Now you must define the following three methods:

  • - (void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region
  • -(void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region
  • -(void)locationManager:(CLLocationManager *)manager didRangeBeacons:(NSArray *)beacons inRegion:(CLBeaconRegion *)region

The names are self explanatory, however the first tells the delegate that the user entered the specified region. The second tells the delegate that the user left the specified region, and the last one tells the delegate that one or more beacons are in range. This last method is mandatory.

The first method only starts to deliver notifications for beacons in the specified region, while the second does the contrary. It stops the delivery of notifications for beacons in the specified region. The complete methods are:

- (void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region {
NSLog(@&quot;Beacon Found&quot;);
[_locationManager startRangingBeaconsInRegion:_beaconRegion];
}
-(void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region {
NSLog(@&quot;Left Region&quot;);
[_locationManager stopRangingBeaconsInRegion:_beaconRegion];
}

Finally, the last method acquires the data of the available beacons and transforms that data in whatever form the user wants. To correctly receive data, create a CLBeacon object. It updates the label and changes the color of the background, taking into consideration the distance of the iBeacon. The complete method source code is the following:

-(void)locationManager:(CLLocationManager *)manager didRangeBeacons:(NSArray *)beacons inRegion:(CLBeaconRegion *)region {
CLBeacon *beacon = [[CLBeacon alloc] init];
beacon = [beacons lastObject];
self.UUID.text = beacon.proximityUUID.UUIDString;
if (beacon.proximity == CLProximityUnknown) {
_distanceLabel.text = @&quot;Unknown Proximity&quot;;
[_view setBackgroundColor:[UIColor blackColor]];
} else if (beacon.proximity == CLProximityImmediate) {
_distanceLabel.text = @&quot;Immediate&quot;;
[_view setBackgroundColor:[UIColor redColor]];
} else if (beacon.proximity == CLProximityNear) {
_distanceLabel.text = @&quot;Near&quot;;
[_view setBackgroundColor:[UIColor orangeColor]];
} else if (beacon.proximity == CLProximityFar) {
_distanceLabel.text = @&quot;Far&quot;;
[_view setBackgroundColor:[UIColor blueColor]];
}
}

You can now Run the app (in two separate devices) and test the beacons. Note that you must depart both devices between five and fifteen meters to leave and re-enter the predefined zone. However, there is a simple solution that you can apply in order to test the app without the need to move that space. You should declare an additional method (- (void)locationManager:(CLLocationManager *)manager didStartMonitoringForRegion:(CLRegion *)region) that states that the region is directly tied to the region of that beacon.

- (void)locationManager:(CLLocationManager *)manager didStartMonitoringForRegion:(CLRegion *)region {
[_locationManager startRangingBeaconsInRegion:_beaconRegion];
}

Additionally, you need to manually call this method in the receiveiBeacon:(id)sender.

[self locationManager:_locationManager didStartMonitoringForRegion:_beaconRegion];

Run the project and test the features! Move away from your iBeacon device and check your interface. You should get screens like the following images when you are within a near distance:

iOS_iB_03
Illustration of a near distance

Or this one when you are far way from your iBeacon device:

iOS_iB_04
Illustration of a far distance

Conclusion

At the end of this tutorial you should be able to define, configure, and use iBeacons. If you have any questions or comments, feel free to leave them below!

Android SDK: Project Manifest

$
0
0

In this series of tutorials we are learning about Android development from scratch and getting acquainted with the basic concepts and practices you need to know in order to start working on the platform. So far we have looked at various parts of an Android project, including its resources. In this tutorial, we will explore the project manifest file.


Introduction

The manifest for a project can be simple or extremely complex depending on what the app does. We will look at the parts of the manifest you need to know about for all apps and will examine those optional parts you’ll need for future projects.

The manifest file can contain many elements and attributes. See the Android Developer Guide for links to all of them. The manifest serves several purposes. It specifies the app package, provides a formal description of the app components, and declares permissions, required API levels, and linked libraries. We will only run through the most essential elements and attributes you can list in the manifest, so be aware that more elements are possible and that there may be additional attributes you can use with the elements we do cover.


1. Manifest Element

In Eclipse, open your project manifest file. You will always find the manifest in the root directory of the project. As we saw before, you can view the manifest in several ways. At the bottom of the editor area you will see tabs for Manifest, Application, Permissions, Instrumentation, and the XML code. Have a quick look through these now. We will use the XML code, so switch to the “AndroidManifest.xml” tab.

Manifest Tab

The elements that appear in the manifest file initially have been populated by Eclipse when you created the project. These are only sufficient for the needs of very simple apps, in most cases you will need to add to the manifest as you build your projects. The root element in the file is the manifest element:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
	package="com.example.myfirstapp"
	android:versionCode="1"
	android:versionName="1.0" ></manifest>

Eclipse populates the manifest element attributes with the package name you chose when creating the project. The version code and name are set to 1 and 1.0 initially. When you release your app to the Play store, then release subsequent updates, you need to update these numbers for each new release. The version name is what users see when your app is listed in the Play store, so you can use whichever version naming convention you like. The version code is not seen by users, and must be a higher number for each release, although it does not have to increment by one each time. If you attempt to upload a new version of an app to Google Play and the version code is not higher than the current version, Play will not allow the upload.


2. Uses SDK Element

First inside the manifest element you should see the uses-sdk element:

<uses-sdk
	android:minSdkVersion="8"
	android:targetSdkVersion="18" />

The element attributes define minimum required API level as well as a target level you plan on testing the project against. Recall that we choose these values when we created the app. You can change these in the manifest after project creation if you need to. For example, you may find that you need to use some aspect of the platform that is not available at your chosen API level. If you change SDK versions, Eclipse rebuilds your project.

Users with devices running an API level lower than the specified minimum will not be able to download and install your app. Listing an API level as target is an indicator that you have tested the app on that version. For reliability you should test your apps on as many API levels as possible.


3. Application Element

Eclipse also inserted an application element in your manifest. The element contains child elements we will look at next. For the moment, let’s look at the opening tag:

<application
	android:allowBackup="true"
	android:icon="@drawable/ic_launcher"
	android:label="@string/app_name"
	android:theme="@style/AppTheme" >

The main attributes to pay attention to are the icon, label, and theme items. The element can take many additional attributes. The icon attribute indicates a file in the app drawables. The default Android icon is selected, but you can add your own icon files and reference them here. The label icon references a string also in the app resources. Open the “res/values” strings XML file. You will see the referenced string listed as follows:

<string name="app_name">MyFirstApp</string>

This should be a readable string as it is displayed to the user in various places including the device menu, next to the launcher icon. You will typically want to alter the string, perhaps to include spaces: “My First App”.

Back in your manifest file, notice the application element theme attribute. Again, this references a resource, you will find it in the “res/values” styles XML file, so have a look there now. Switch back to the manifest again. If you later decide to define your own application styles, you can reference them in the theme attribute.


4. Activity Elements

Inside the application element, you will see an activity element for the main Activity class you created when you started the project. This activity element also contains child elements we will look at next. Look at the opening tag first:

<activity
	android:name="com.example.myfirstapp.MainActivity"
	android:label="@string/app_name" >

The name attribute references the class using its fully qualified path in the app package. The label allows you to control what appears as the window title when the Activity is on screen. By default it is the same as the app name so you can leave it as is in most cases.

As your apps become more complex, you will add more Activities to them, one for each screen in the UI. Each time you add a new Activity class to your app, you need to add an element for it inside the application element, like in the following example:

<activity android:name=".About" ></activity>

As you can see, you do not always need to include the full package name. The shortened form above will work as long as the Activity class (named “About”) is in the package defined in the manifest element. Activity elements can take many attributes determining how the user can interact with them.


5. Intent Filters

Inside the main activity element, you will see an intent-filter element:

<intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter>

The Intent Filter describes what Intents the parent activity can respond to. On Android, an Intent is a data object that is passed to an Activity when it starts. When you launch one Activity from another within your apps you will use Intents, but they can also be passed between apps.

The Intent Filter for the main activity indicates that it should start when the app is launched. It does this using the action element, which lists the “MAIN” action. The category element describes the Intent Filter by category name, in this case “LAUNCHER”. Both of these in conjunction specify that your app should use the Activity as its main entry point, and that this entry point should be used when the app is launched.

Intent Filters can contain many child elements, including data specifications. For more information, see the Intent and Intent Filters section in the Android Developer Guide. The activity element can contain additional child elements alongside intent-filter such as metadata, which can define a name-value pair of data items.


6. Uses Permission

We have looked at all of the manifest elements Eclipse includes when you create your project. Let’s now look at some others you may need in future projects. The uses-permission element allows you to request permission for your app to do certain things the user must grant permission for. When the user views your app in the Play store, the permissions will be displayed to them before downloading the app. If they choose to go ahead, they must accept the permissions so that your app can run.

Permissions you must request in the manifest include using Internet data, writing to external storage, and accessing devices features such as the camera. The following example demonstrates this concept:

<uses-permission android:name="android.permission.INTERNET" />

There are several potential permissions your apps can request. See the Manifest.permission page on the API reference.


7. User Devices

A range of manifest elements can be used to describe required hardware and software features for an app. These include the uses-configuration element, in which you can specify requirements for navigation, keyboard, and touchscreen options. In the uses-feature element, you can list a single feature required in either hardware or software, using the feature name and a Boolean flag. These features include Bluetooth and camera options such as flash, location detection, and sensors. The supports-screens element lets you define screen sizes supported by your app, specifying attributes related to both size and density.


8. Other Elements

The elements we’ve explored are most likely to be used for your initial apps. However, there are other elements used in different types of applications. The initial project we created is for a standard app launched through the user menu and presents one or more Activity screens to the user. Other types of apps include widgets and applications running ongoing background processes, handling data access, and receiving system announcements.

Apps using background processing typically do this using Service classes on Android. This requires listing the service element in the manifest, one for each Service class as with Activities. Content Providers in Android apps are responsible for managing access to a data source. These are listed using the provider element. Finally, the receiver element is listed in the manifest file if an app wants to receive Intents from other apps or from the system itself.


Conclusion

We’ve covered the essential features of the manifest file in Android apps. Each time you create an app, Eclipse populates the file with the main elements you need to start with. As you build functionality into the app, you will continually add content to the manifest to ensure the app as a whole can function. When you encounter problems running your apps on actual or virtual devices during development, this will sometimes be due to a missing element in the manifest. In the next part of the series, we will look at how Android apps store and access data.

Android SDK: App Data

$
0
0

In this series, we are learning about Android SDK development from scratch. We have already become acquainted with the structure and basic elements in an Android application, including the resources, Manifest, and user interface. As soon as you start to develop functional apps for Android, you will need to store data of one kind or another. The Android platform offers a range of options for data storage in your apps, which we will examine in this tutorial.


Introduction

Broadly speaking, there are five main options for data storage in Android apps: by saving data to the app Shared Preferences, to internal storage (which is private to your app), to external storage (which is public to the device), to databases, and to Web resources accessed via the device’s Internet connection. We will not demonstrate each of these options fully, but will take an overview of the basics with each approach, giving you a sense of how to choose a storage option each time you need persistent data.


1. Shared Preferences

Step 1

Shared Preferences let you store primitive data types in key-value pairs. The app Shared Preferences file is typically the simplest data storage option, but it is inherently limited in terms of what you can store. You can save primitive type numbers (int, long, and float), boolean values, and text Strings. You assign a name to each value you store and retrieve it each subsequent time the app runs. Since you are most likely to use the Shared Preferences in the first apps you create, we will run through the process in a little more detail than the other options, which you can build your knowledge of as needed.

You can try this code out in your main Activity class and test it when we run the app later on in this series. Shared Preferences are ideally suited to user configuration options for your apps, like to choose appearance settings. Remember we created a simple button that when the user clicked it, the text displayed on it changed to “Ouch”. Let’s imagine that once the user clicked the button once, we want the button to maintain the “Ouch” text, even on subsequent runs of the app. This means that the initial text only appears until the first time the user clicks the button.

Let’s add some Shared Preferences to the app. At the top of the class, before the onCreate method, let’s choose a name for the Shared Preferences:

public static final String MY_APP_PREFS = &quot;MyAppPrefs&quot;;

Using the “public static” modifiers lets us access this variable in any class within the app, so we only need to store the preferences name String here. We use uppercase because the variable is a constant, hence the “final” modifier. Each time you retrieve or set a data item in the app preferences, you must use the same name.

Step 2

Let’s write the Shared Preferences now. In your onClick method, after the line in which you set the “Ouch” text on the button, retrieve the Shared Preferences using their name:

SharedPreferences thePrefs = getSharedPreferences(MY_APP_PREFS, 0);

You need to add an import for the “android.content.SharedPreferences” class. Hover over the “SharedPreferences” text and use the Eclipse prompts to do this. The first parameter is the preferences name we defined, the second is the mode, which we use for the default option.

Now you need to retrieve an Editor for the Shared Preferences if you want to set values:

SharedPreferences.Editor prefsEd = thePrefs.edit();

Now we can write a value to the Shared Preferences:

prefsEd.putBoolean(&quot;btnPressed&quot;, true);

We use a Boolean type since the user has either pressed the button or not. The Editor provides specific methods for the different types you can store in the Shared Preferences, with each method taking name and value parameters. Finally, we need to commit the edits:

prefsEd.commit();

Step 3

Let’s now use the stored value to determine what should display when the user runs the app. In onCreate, after the existing code, get the Shared Preferences:

SharedPreferences thePrefs = getSharedPreferences(MY_APP_PREFS, 0);

We don’t need an editor this time as we are only retrieving a value:

boolean pressed = thePrefs.getBoolean(&quot;btnPressed&quot;, false);

We retrieve the value using the same name we set it with, reading the result into a variable. If the value has not yet been set, the second parameter is returned. This is the default value, which is false. Now let’s use the value:

if(pressed) theButton.setText(&quot;Ouch&quot;);

If the user pressed the button when the app was run before, the button displays “Ouch” straight away. You can see this in action when we run the app later in the series. This is a trivial example to demonstrate the process of using Shared Preferences. You will find them most useful in your own apps for user preferences in terms of the app’s appearance and behavior.


2. Private Internal Files

Step 1

You can save files to both the internal and external storage on the user’s device. If you save a file to internal storage, Android treats this as private to your app. Such files are essentially part of your app as far as the device is concerned, there is no direct access to them outside of the app, and they are removed if the app itself is removed.

You can create a file in internal storage using an output stream as follows:

FileOutputStream fileOut = openFileOutput(&quot;my_file&quot;, Context.MODE_PRIVATE);

You need to add an import for the “java.io.FileOutputStream” class. We pass a file name and mode, choosing private mode so that the file can only be used by the app. If you try adding this code to your Activity now, for example in the onClick method, Eclipse will indicate an error. This is because when you carry out input/ output operations your app may encounter errors that you need to take measures to cope with. If your input/ output operation cannot complete it, an Exception is thrown and your app will stop functioning. To keep the app running, if this happens, we enclose our input/ output code in a try block:

try{
	FileOutputStream fileOut = openFileOutput(&quot;my_file&quot;, Context.MODE_PRIVATE);
}
catch(IOException ioe){
	Log.e(&quot;APP_TAG&quot;, &quot;IO Exception&quot;, ioe);
}

If the input/ output operation causes an Exception, the code inside the catch block executes, which simply writes the error details to the Log. You will use the Log class often in your apps (import “android.util.Log”), as it lets you see what is happening as the code executes. You can define a class variable for the String tag we use as first parameter here. Then you can see details of the Exception in the Android LogCat if something goes wrong.

Step 2

Back in the try block, after creating the file output stream, you can attempt to write to the file:

String fileContent = &quot;my data file content&quot;;
fileOut.write(fileContent.getBytes());

Once you have written what you need to the file, you should close it:

fileOut.close();

Step 3

When you need to retrieve the content of internal files, you can use the following process:

try{
	FileInputStream fileIn = openFileInput(&quot;my_file&quot;);
	//read the file
}
catch(IOException ioe){
	Log.e(&quot;APP_TAG&quot;, &quot;IO Exception&quot;, ioe);
}

Inside the try block, read the file contents using a Buffered Reader:

InputStreamReader streamIn = new InputStreamReader(fileIn);
BufferedReader fileRead = new BufferedReader(streamIn);
StringBuilder fileBuild = new StringBuilder(&quot;&quot;);
String fileLine=fileRead.readLine();
while(fileLine!=null){
	fileBuild.append(fileLine+&quot;\n&quot;);
	fileLine=fileRead.readLine();
}
String fileText = fileBuild.toString();
streamIn.close();

Don’t be intimidated by the number of different objects involved, this is standard for Java input/ output. The while loop executes for each line in the file. After execution, the “fileText” variable stores the file content as a String you can then make use of.


3. Public External Files

Step 1

Your apps can save files to external storage if the user device has some available. External storage can be an SD card or other removable media, or it can be internal storage that the user cannot remove but that the system regards as external. When you save a file to external storage, it is public and there is no way for you to stop the user or another application from accessing it.

Before you attempt to save data to external storage, you must first check that there is some available, as this will not always be the case:

String extStorageState = Environment.getExternalStorageState();

The system returns the information as a String, which you can then analyze, checking it against the Environment class fields for various external storage states:

if(Environment.MEDIA_MOUNTED.equals(extStorageState)){
	//ok to go ahead and read/ write to external storage
}
else if(Environment.MEDIA_MOUNTED_READ_ONLY.equals(extStorageState)){
	//can only read
}
else{
	//cannot read or write
}

Even if there is external storage on the device, we cannot assume that the app can write to it.

Step 2

After verifying that you can write to external storage, you then need to retrieve the directory location to save your files in. The following applies to apps targeting API levels 8 and onwards:

File myFile = new File(getExternalFilesDir(null), &quot;MyFile.txt&quot;);

You can then write to and read from the file. You will also need the following permission in your Manifest file:

&lt;uses-permission android:name=&quot;android.permission.WRITE_EXTERNAL_STORAGE&quot; /&gt;

When your apps become more advanced, you may wish to save to files that are shared by other applications. In such cases, you can use the various public directories for common items, such as pictures and music files.


4. Databases

As soon as your apps require more complex structured data than you can reasonably store in Shared Preferences or internal/ external files, you should consider using databases. Android provides support for creating and accessing SQLite databases within your apps. When you create a database, it is private to your app.

The recommended way to utilize SQLite databases in your Android apps is to use a class which extends SQLiteOpenHelper. Inside this class, define the properties of the database, creating class variables in which you define the database table names and their SQL creation strings, as in the following example:

private static final String NOTE_TABLE_CREATE =&quot;CREATE TABLE Note (noteID INTEGER PRIMARY KEY AUTOINCREMENT, &quot; +&quot;noteTxt TEXT);&quot;;

This example represents a very simple table with two columns, one for ID and the other for text, with each record storing a user note. Inside your SQLiteOpenHelper class, you can override the onCreate method to create your database. Elsewhere in the app, like in an Activity class, you can then access the database via the SQLiteOpenHelper, using the getWritableDatabase method to insert new records and the getReadableDatabase method to query for existing records, you can then display within your app UI.

When iterating through query results, your apps will use the Cursor class, which reference each row in your result set in turn.


5. Internet Data

Many apps use Internet data resources, with the app sometimes essentially comprising an interface to a Web data source. You can use the Internet connection on the user device to store and retrieve data from the Web whenever the user has a functioning Internet connection. To do so, you need to add the “android.permission.INTERNET” permission to your Manifest.

If you want to fetch Internet data in your apps, you need to make sure you carry out this processing off the app’s main UI thread. By using an AsyncTask, you can fetch data from the Web in a background process, write the results to the UI when they arrive, and let the UI continue to function while they are fetched.

You can add an inner AsyncTask class inside an Activity class, then create an instance of the AsyncTask in the Activity whenever you want the data fetched. By including the doInBackground and onPostExecute methods in your AsyncTask, you can retrieve the results of fetching the data in the Activity, letting you write them to the user interface.

Fetching Web data is an intermediate task better left until you have grasped the basics of Android development using data on the device. However, you may find it useful for many apps as it lets you exploit the user device connectivity. Java and Android provide utilities for handling returned structured data, such as JSON feeds.


Conclusion

This tutorial gave you an overview of your data storage choices when developing Android apps. Whatever option you choose is determined by the details of the app you are working on, as the methods of each option are suited to specific needs. In the next part of this series, we will look at connecting physical devices to your Eclipse installation as well as creating virtual devices. After that, we will explore running apps on either type of device. Towards the end of the series, we will examine common classes and the Android Activity lifecycle, preparing you to start working on your own apps.

iOS SDK: Build a Facts Game – Project Setup

$
0
0

This tutorial will teach you how to use the Sprite Kit framework to create a question-based facts game. It is designed for both novice and advanced users. Along the way, you will apply the Sprite Kit core. The Facts tutorial series is divided into three parts in order to completely cover each topic.


Introduction

This series of tutorials is divided into three parts: Project Setup, Interface Creation, and Game logic. Each part will produce a practical result, and the sum of all parts will produce the final game. After the three part tutorial, readers will be able to create a simple question-and-answer tap game featuring sounds, animations, menus, rules, timers, and UIKit interaction. Despite the fact that each part can be read independently, for a better understanding we suggest that you follow the tutorials in order. We also included the source code for each part separately, thus providing a way to start the tutorial at any section.

At the end of this tutorial, the result will look like this:

Image0
Illustration of the Final Result – Facts

1. Initial Setup

Start a new SpriteKit Xcode project and name it Facts. The Deployment information used across the three parts is:

  • Deployment Target: 7
  • Devices: iPad
  • Device Orientation: Portrait
  • Hide status bar style

Note that the following four frameworks are automatically included in the project: CoreGraphics, UIKit, SpriteKit, and Foundation. You will see three classes, an image (Spaceship.png) and a Main.storyboard file. You can delete the image since you will not use it.

Now open the Myscene.m and comment the whole -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event method. You do not need to create a tap gesture in this scene because you will use several UIKit UIButtons for user interaction.


2. Backgrounds, Labels, and Buttons

Start by changing the background color of the SKScene by changing the self.backgroundColor properties. Note that it uses a SKColor object with three properties for red, blue, and green components. Now change the myLabel text to “Facts!!” or to any other title of your interest.

The next step is to add the necessary resources to your project; find them in the Resources folder. Despite the fact that you will not use all the resources now, you should add them all. Since you will use the UIKit framework, add a specific method (-(void) didMoveToView:(SKView *)view) that detects if the scene transition occurred without problems. If no problems occurs, the app loads resources into the screen. Add the method to your code. Inside you will declare three buttons: one for starting the game, one for options, and the last one to exit the app.

Add three UIButtons to your MyScene.m. It will look like this:

@implementation MyScene {
    UIButton *startButton;
    UIButton *optionsButton;
    UIButton *exitButton;
}

Each button has specific configurations regarding the frame’s location and size, the background color, and the background image. You should try to create a UIButton and add it to the scene view. The buttons should look like the following snippet:

-(void) didMoveToView:(SKView *)view{
    startButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    startButton.frame = CGRectMake(CGRectGetMidX(self.frame)-100, CGRectGetMidY(self.frame), 200, 70.0);
    startButton.backgroundColor = [UIColor clearColor];
    [startButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal ];
    UIImage *buttonImageNormal = [UIImage imageNamed:@"StartBtn.png"];
    UIImage *strechableButtonImageNormal = [buttonImageNormal stretchableImageWithLeftCapWidth:12 topCapHeight:0];
    [startButton setBackgroundImage:strechableButtonImageNormal forState:UIControlStateNormal];
    [self.view addSubview:startButton];
    optionsButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    optionsButton.frame = CGRectMake(CGRectGetMidX(self.frame)-100, CGRectGetMidY(self.frame)+90, 200, 70.0);
    optionsButton.backgroundColor = [UIColor clearColor];
    [optionsButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal ];
    UIImage *buttonOptionsImageNormal = [UIImage imageNamed:@"OptionsBtn.png"];
    UIImage *strechableButtonOptionsImageNormal = [buttonOptionsImageNormal stretchableImageWithLeftCapWidth:12 topCapHeight:0];
    [optionsButton setBackgroundImage:strechableButtonOptionsImageNormal forState:UIControlStateNormal];
    [self.view addSubview:optionsButton];
    exitButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    exitButton.frame = CGRectMake(CGRectGetMidX(self.frame)-100, CGRectGetMidY(self.frame)+180, 200, 70.0);
    exitButton.backgroundColor = [UIColor clearColor];
    [exitButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal ];
    UIImage *buttonExitImageNormal = [UIImage imageNamed:@"ExitBtn.png"];
    UIImage *strechableButtonExitImageNormal = [buttonExitImageNormal stretchableImageWithLeftCapWidth:12 topCapHeight:0];
    [exitButton setBackgroundImage:strechableButtonExitImageNormal forState:UIControlStateNormal];
    [self.view addSubview:exitButton];
}

Run the project and see the new root interface. If you want, you can adjust the location, size, and position of the interface objects. If you want to learn more about the SKLabelNode or UIButton, we advise you to play with that classes a bit more. The interface should look similar to the following image:

Image1
Root interface

It is now time to add more classes to your project.


3. New Game and Options SKScenes

Step 1

Since you added several buttons, it is now time to use them to redirect the user to another interface. Add two new classes. Choose File -> New -> File and Objective-C class. Name the classes FactsScene and OptionsScene. Note that both will be a superclass of SKScene.

Four new files are available in you project: FactsScene.h, FactsScene.m, OptionsScene.h, and OptionsScene.m. Note that the implementation files of both classes are almost empty. Therefore, you must add the class initializers. For both classes use the -initWithSize: method. Try and add it by yourself. If you have any trouble, the following snippet will help you:

-(id)initWithSize:(CGSize)size{
    if (self = [super initWithSize:size]) {
        NSLog(@"Opstions Scene");
    }
    return self;
}

Once again you should apply it for both classes. Now that you have the classes initializers, it is now time to modify the UIButton code from the last step to change between classes. Go back to MyScene.m and import both classes in the import section:

  #import "OptionsScene.h"
  #import "FactsScene.h"

Now in the startButton, optionsButton, and exitButton, you need to add a custom action. At each button, add the corresponding line of code.

  [startButton addTarget:self action:@selector(moveToGame) forControlEvents:UIControlEventTouchUpInside];
  [optionsButton addTarget:self action:@selector(moveToOptions) forControlEvents:UIControlEventTouchUpInside];
  [exitButton addTarget:self action:@selector(endApplication) forControlEvents:UIControlEventTouchUpInside];

You should see three warnings (undeclared selector). Don’t worry! It is now time to add those methods to your class.

  -(void) moveToGame {}
  -(void) moveToOptions {}
  -(void) endApplication {}

Each one is responsible for a specific action and the name of each method is self-explanatory. The -(void) moveToGame and -(void) moveToOptions methods are similar, since both are used to create a transition from this SKScene to another. At each method, you should create a SKScene destination object and transition object, and present the new scene. Note that since you are using UIKit objects, you also need to remove them from the scene at the SKScene transitions. If you experience trouble with these steps, the following snippets will guide you:

-(void) moveToGame{
    NSLog(@"moveToGame");
    FactsScene* factsScene = [[FactsScene alloc] initWithSize:CGSizeMake(CGRectGetMaxX(self.frame), CGRectGetMaxY(self.frame))];
    SKTransition* transition = [SKTransition revealWithDirection:SKTransitionDirectionUp duration:1];
    [startButton removeFromSuperview];
    [optionsButton removeFromSuperview];
    [exitButton removeFromSuperview];
    [self.scene.view presentScene:factsScene transition:transition];
}
-(void) moveToOptions{
    NSLog(@"moveToOptions");
    OptionsScene* optionsScene = [[OptionsScene alloc] initWithSize:CGSizeMake(CGRectGetMaxX(self.frame), CGRectGetMaxY(self.frame))];
    SKTransition* transition = [SKTransition revealWithDirection:SKTransitionDirectionLeft duration:1];
    [startButton removeFromSuperview];
    [optionsButton removeFromSuperview];
    [exitButton removeFromSuperview];
    [self.scene.view presentScene:optionsScene transition:transition];
}

The last method -(void) endApplication is simpler since it is only used to end the application.

-(void) endApplication{
    [startButton removeFromSuperview];
    [optionsButton removeFromSuperview];
    [exitButton removeFromSuperview];
    exit(0);
}

Step 2

It is now time to Run the code and test the new features. If everything is fine you should be able to change the default view into the New Game view and Options view. However, you cannot go back to the main menu. Let’s change that right now.

Your next steps are to add a UIButton to the Options scene, program it to make a transition back to the main menu, and choose to create a transition effect (or not). In order to do this, several steps are necessary:

  • Add the -(void) didMoveToView:(SKView *)view method
  • Add a UIButton object
  • Configure the UIButton
  • Add the @selector method
  • Import the MyScene.h

First, go to the OptionsScene.h and add:

  @property (nonatomic, retain) UIButton* backButton;

Now change your attention to OptionsScene.m. The snippets for the pseudo-code are to add the didMoveTiView method, the UIButton, and the button configuration.

-(void) didMoveToView:(SKView *)view{
  _backButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
  _backButton.frame = CGRectMake(CGRectGetMidX(self.frame)-100, CGRectGetMidY(self.frame)+180, 200, 70.0);
  _backButton.backgroundColor = [UIColor clearColor];
  [_backButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal ];
  UIImage *buttonExitImageNormal = [UIImage imageNamed:@"ExitBtn.png"];
  UIImage *strechableButtonExitImageNormal = [buttonExitImageNormal stretchableImageWithLeftCapWidth:12 topCapHeight:0];
  [_backButton setBackgroundImage:strechableButtonExitImageNormal forState:UIControlStateNormal];
  [_backButton addTarget:self action:@selector(moveToHome) forControlEvents:UIControlEventTouchUpInside];
  [self.view addSubview:_backButton];
  }

Next, add the @selector method.

-(void) moveToHome{
  MyScene* myScene = [[MyScene alloc] initWithSize:CGSizeMake(CGRectGetMaxX(self.frame), CGRectGetMaxY(self.frame))];
  [_backButton removeFromSuperview];
  [self.scene.view presentScene:myScene];
}

Run your code to check if everything is up and running. You can now jump from the root interface to the OptionsScene and back again. Now, we can populate the Options scene.


4. Options SKScene

Step 1

The options of a game is where the user can arrange several configurations regarding the game. For now, you will only focus on two options: music and sound. You need to add a SKLabelNode, a UISwitch, and an AVAudioPlayer object to OptionsScene.h:

  @property (nonatomic, retain) IBOutlet UISwitch *musicSwitch;
  @property (nonatomic, retain) IBOutlet UISwitch *soundSwitch;
  @property (nonatomic, retain) SKLabelNode* soundTitle;
  @property (nonatomic, retain) SKLabelNode* musicTitle;

Then on the OptionsScene.m inside the didMoveToView method, allocate the objects as:

_soundSwitch = [[UISwitch alloc] initWithFrame:CGRectMake(CGRectGetMidX(self.frame)+50, CGRectGetMidY(self.frame)-26, 100, 100)];[_soundSwitch addTarget: self action: @selector(flipMusicAndSound:) forControlEvents:UIControlEventValueChanged];
[self.view addSubview: _soundSwitch];
_musicSwitch = [[UISwitch alloc] initWithFrame:CGRectMake(CGRectGetMidX(self.frame)+50, CGRectGetMidY(self.frame)+50, 100, 100)];
[_musicSwitch addTarget: self action: @selector(flipMusicAndSound:) forControlEvents:UIControlEventValueChanged];
[self.view addSubview: _musicSwitch];
_soundTitle = [SKLabelNode labelNodeWithFontNamed:@"Chalkduster"];
[_soundTitle setText:@"Sound"];
[_soundTitle setFontSize:40];
[_soundTitle setPosition:CGPointMake(CGRectGetMidX(self.frame)-80, CGRectGetMidY(self.frame))];
[self addChild:_soundTitle];
_musicTitle = [SKLabelNode labelNodeWithFontNamed:@"Chalkduster"];
[_musicTitle setText:@"Music"];
[_musicTitle setFontSize:40];
[_musicTitle setPosition:CGPointMake(CGRectGetMidX(self.frame)-80, CGRectGetMidY(self.frame)-80)];
[self addChild:_musicTitle];

You will get a warning. To correct it, add the flipMusicAndSound method. This method checks the state of _soundSwitch and _musicSwitch UISwitches, and sets a default key to each property using NSUserDefaults. Before you complete the method, you should add the NSUserDefaults object to the class.

@implementation OptionsScene{
    NSUserDefaults* defaults;
}

Then you should allocate it in the initWithSize method as:

defaults = [NSUserDefaults standardUserDefaults];

Step 2

Now you are ready to use the advantages of NSUserDefaults. You will use it to store the state of the sound and music properties across the whole app. You can write and complete the flipMusicAndSound method. You will use the integer value 1 to set the sound and music on, and 0 otherwise. The flipMusicAndSound is below.

- (IBAction)flipMusicAndSound:(id)sender {
    if (_musicSwitch.on) {
        [defaults setInteger:1 forKey:@"music"];
    }
    else {
        [defaults setInteger:0 forKey:@"music"];
    }
    if (_soundSwitch.on) {
        [defaults setInteger:1 forKey:@"sound"];
    }
    else {
        [defaults setInteger:0 forKey:@"sound"];
    }
}

If you Run the project and play with both switches, you will see that every time you go to the OptionsScene both switches have a default state, rather than the last state defined. To change that, we must read the NSUserDefaults object at the didMoveToView method.

You will define two variables for sound and music and check each inherent property key. It is a very simple and logical decision test. If you are unsure how to do this, the next snippet will assist you.

  long soundDefaults = [defaults integerForKey:@"sound"];
  long musicDefaults = [defaults integerForKey:@"music"];
  if (soundDefaults == 1) {
    [_soundSwitch setOn:YES animated:YES];
  }
  else {
    [_soundSwitch setOn:FALSE animated:YES];
  }
  if (musicDefaults == 1) {
    [_musicSwitch setOn:YES animated:YES];
  } else{
    [_musicSwitch setOn:FALSE animated:YES];
  }

The last step in OptionsScene.m file is to remove the UISwitch items from the superview every time the user taps the back button:

[_soundSwitch removeFromSuperview];
[_musicSwitch removeFromSuperview];

Here’s an illustration of the Options interface:

Image2
Options Interface

Step 3

Move to the FactsScene.m. Now we can add the sound and music elements. Like with the OptionsScene, we need to use NSUserDefaults to get the value for music and sound. We will also need an object to store the music path and another for the iOS music player. Thus we will declare them as:

@implementation FactsScene{
    NSUserDefaults* defaults;
    NSString* musicPath;
}

Also in the FactsScene.h:

@property (nonatomic, strong) AVAudioPlayer* musicPlayer;

You must declare (as you did with the last class) the method -(void) didMoveToView:(SKView *)view. Inside you need to check if the music and sound preferences are on and allocate the music preferences. Both can be achieved through:

  musicPath = [[NSBundle mainBundle] pathForResource:@"music" ofType:@"mp3"];
  _musicPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:musicPath] error:NULL];
  _musicPlayer.numberOfLoops = -1; // loop forever
  _musicPlayer.volume = 0.7;
  long musicFlag = [defaults integerForKey:@"music"];
  if (musicFlag == 1){
    [_musicPlayer play];
  } else {
    [_musicPlayer stop];
  }

The above-mentioned code only starts or stops the music if its property is on. We also want to create sounds when a tap occurs. So, we need to catch the touches interactions and react accordingly.

Do you remember the -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event method from the MyScene.m implementation file? You will define it and use it here.

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
    for (UITouch *touch in touches) {
        [self touchWillProduceASound:@"False"];
    }
}

Note that, the -(void) touchWillProduceASound:(NSString*)answer is not declared yet. Declare it. It’s used to test if a given touch is “correct” or “incorrect” (here will be more on that in the next tutorial). It parses the (NSString*)answer and produces a sound accordingly to the content of that NSString.

The sound is created with the SKAction object. It creates a sound object and plays a specific sound. Once again, this occurs only if the sound property (given by the NSUserDefaults) is on.

-(void) touchWillProduceASound:(NSString*)answer{
    long soundFlag = [defaults integerForKey:@"sound"];
    if (soundFlag == 1){
        SKAction* sound;
        if ([answer isEqualToString:@"False"]) {
            sound = [SKAction playSoundFileNamed:@"beep.mp3" waitForCompletion:YES];
            NSLog(@"inside");
        }
        [self runAction:sound];
    }
}

Run the project and test the new music and sound interactions. Activate and deactivate both the sound and music UISwitches and move to the New Game scene to test them correctly.


Conclusion

This is the end of the first tutorial! At this point you can initiate and configure a SpriteKit project, add and initialize SKScene objects, navigate between SKScene objects, interact between SpriteKit and UIKit frameworks, and add and remove sounds and music. In the following tutorials, you will deal with Interface Creation and Game Logic.

Android SDK: Virtual & Physical Devices

$
0
0

We are learning about Android app development in this series. We already looked at the basic elements in an Android project and touched on user interface design and data storage along the way. In this tutorial, we are going to explore how to run and interact with your apps on physical and virtual devices. In the next part of the series, we will work through the process of running an app on a physical device and on the emulator. In this part, we’ll look at getting our physical and virtual devices set up in Eclipse.

Introduction

When you develop Android app for release to the public, you should always try to test them on a real device as well as the emulator. With the emulator, you can configure virtual devices for various hardware and software features. While this is not quite as reliable as testing on a range of real devices, it does help to bridge the gap between the devices you have access to and the extremely wide range of Android devices in use. Certain hardware and software features are not available on the emulator, but you can test for most of the functions you are likely to use in your first apps.


1. Hardware Devices

Step 1

When you develop Android apps, you should primarily aim to test them on a physical hardware device. As well as providing a real sense of how your app will look, feel, and function for users, hardware devices are the only way to test certain functions, such as telephony. If you use a hardware device during development, you can then run and test the app on a range of virtual devices configured to emulate the hardware and software features your hardware device does not have.

Let’s start by connecting a hardware device to Eclipse. Connect an Android device to your computer by USB. You may need to enable USB debugging on your device. To do this, browse to the device Settings, then choose “Developer Options”, “Advanced Settings” or “Applications”, and “Development”. Select the checkbox to enable USB debugging. If you’re using a device running Android 4.2 or newer, you may need to set the developer options section to display. Browse to “About phone” then tap the listing for “Build number” repeatedly (seven times) then navigate back to the previous screen.

Tip: You may also need to prepare your system to detect the Android device when you connect it, although in many cases this happens automatically. If you have trouble detecting the device on Windows, download and install a USB driver. If you’re on Linux and having trouble detecting the device, you may need to use a udev file in which you list the device manufacturer. See the Developer Guide for instructions on how to do this.

Step 2

Once your system detects the connected Android device, you can interact with it in Eclipse. When you start running your apps in the next tutorial, you will see this in action. For now, just switch to the DDMS View. In Eclipse, select “Window”, “Open Perspective”, and “DDMS”. You should see your device listed in the Devices View on the left. You will also see the LogCat View begin to populate with messages about processes executing on the device.

Take a moment to look at the File Explorer View with your device selected in the Devices View. You will see the files and folders on the device. As you can see, these Views let you explore the connected device as you run, test, and debug your apps. You can also use the buttons in the Devices View, which include a Screen Capture button you may wish to use when preparing images of your apps for release.


2. Virtual Devices

Step 1

Now let’s look at creating some virtual devices. In Eclipse, open the AVD Manager by selecting “Window” then “Android Virtual Device Manager”. The AVD Manager displays two tabs, one in which you can create and launch virtual devices and another for managing reusable definitions for devices. There may be times when you need to create your own AVDs with configurations to test particular app features from scratch, but in the beginning you will find it much quicker and easier to use the existing device definitions. Now switch to the “Device Definitions” tab.

You will see a list of device definitions in the AVD Manager. This provides a way to store device configurations you can later re-use. You can create your own device definitions using the “New Device” button. Click it now to see the interface.

New Device

Here you can configure many aspects of the virtual device software and hardware, including screen size and resolution, sensors, camera, input, density, and buttons. When you create a new device, it appears within the list alongside the existing definitions. You should try to choose meaningful names for any definitions you configure so that you can identify them at a glance in the list. You can stick to the existing definitions for your first few app runs, so click “Cancel” for now.

Step 2

You have two options to utilize existing device definitions: either clone an existing device definition then tweak its properties or create a virtual device instance based on its existing definition. Select a device from the list and click “Clone”.

Clone Device

The Clone Device window fields are automatically populated with the properties matching the selected definition. To use these device properties as a basis for a slightly different device, leave all of the fields as they are and click “Clone Device”. A copy of the device will appear in the list.

Cloned Device in List

As you can see, you can identify user-defined devices at a glance as the Android device definitions and user device definitions are color coded. You can only edit user-defined definitions, so select your cloned device in the list and click “Edit”.

Edit Device

You can now edit any aspects of the device you like and click “Edit Device” to apply your configuration. You can now create AVD instances based on the listed device definitions.

Step 3

Now you can see one of the device definitions in action by creating an AVD based on it and running it on the emulator. Select a device definition from the list and click “Create AVD”. In the window, you can configure the instance or can leave it as it stands based on the definition. See the Developer Guide for a list of AVD options. Click “OK” to create the AVD.

Create AVD

Eclipse will switch back to the Android Virtual Device tab where your new device will appear. With the new AVD selected, click “Start” to run it.

Created Devices

Click “Launch” in the pop-up window that appears. Eclipse will start to run the emulator with your defined AVD on it. The device may take a few minutes to start up. You can close the AVD Manager once you have a device running.

Step 4

Where appropriate, the emulator displays virtual versions of the device hardware controls. You can interact with these by clicking them with your mouse. In addition, there are a number of keyboard shortcuts on the emulator that you will likely find useful, including the “Home” key for the device home button, ESC for the device back button, and F2 for the menu button. See the Developer Guide for a list of emulator shortcuts.

Device Display

Depending on the AVD you created, you may need to press F2 or click “OK” to remove the lock screen. As you can see, the emulator displays what you would see on a physical device. Take a few minutes to explore the virtual device now, browse the app menu, and launch a few apps.

Explore Device

Launch the Browser app on the virtual device. Click in the navigation bar and enter a URL to visit. You can use your computer keyboard to type on the device. The emulator automatically uses any Internet connection you have on your computer, so you can test Web connectivity functions in your apps.

Device Browser

Step 5

With your AVD still running, switch back to Eclipse and open the DDMS perspective again. You will see the virtual device listed in the Devices View, as with the physical device you connected. Eclipse will display a list of processes running on the device. For selecting a process, various buttons in the Devices View are enabled. Take a moment to look at these now. You can use these tools when you debug future apps.

AVD in DDMS

Conclusion

Now we are acquainted with the process of using a hardware or emulated device in Eclipse. In the next tutorial, we will run our app on a device from Eclipse. After that, we will explore common Android components and the Activity lifecycle, before pointing you in the direction of resources for future learning. As you develop your first few apps, you may wish to look back at these tutorials as a reminder of the options available when creating and interacting with devices from Eclipse.

iOS SDK: Build a Facts Game – Interface Creation

$
0
0

This tutorial will teach you how to use the Sprite Kit framework to create a question-based Facts game. It is designed for both novice and advanced users. Along the way, you will apply the Sprite Kit core. The Facts Game tutorials are divided into three parts in order to completely cover each section. After this three part tutorial, the readers will be able to create a simple question-and-answer tap game featuring sounds, animations, menus, rules, timers, and UIKit interaction.


Introduction

This series is divided into three parts: Project Setup, Interface Creation, and Game Logic. Each part will produce a practical result, and the sum of all parts will produce the final game. Despite the fact that each part can be read independently, for a better understanding and guidance, we suggest that the tutorial be followed step by step. We also included the source code for each part separately. Thus, providing a way to start the tutorial in any part of the series.

This is the second part of our Facts Game with Sprite Kit tutorial series. In this tutorial, you will program the level selection and main game scene interface. This tutorial focuses on several aspects such as, custom UITableView, custom class initializers, property lists, and SKActions. We will explain everything further below. If you haven’t completed the first part of the series yet, you can download the project and pickup exactly where we left off.

This is what our end result will look like:

Image0
Illustration of the Final Result – Facts

1. Level Select

Step 1

The main objective of this game is to create multiple questions divided by several levels. This way, you need to form a customized interface to choose the level you want to play. In order to achieve this, you need to add another Objective-C class (File -> New -> File). Name it LevelSelect and choose the SKScene as the superclass. You will see two new files in your project.

For the level selection, you will use the UITableView view and configure it with several properties. Additionally, you also need to name the levels and their descriptions. In the LevelSelect.h you should add those properties. The following snippet will help you:

@property (nonatomic, retain) UIButton* backButton;
@property (retain, nonatomic) IBOutlet UITableView *tableView;
@property (strong, nonatomic) NSArray *levelsArray;
@property (strong, nonatomic) NSArray *levelsDescriptionArray;

The snippet also contains a UIButton called backButton. At this moment, the button is self-explanatory; it helps the user go back from the level select interface to the main interface.

Step 2

Next, focus on the LevelSelect.m. The first step is to add the -(id)initWithSize:(CGSize)size method. In this class, you will only configure the background color. You can choose the color that you like the most.

-(id)initWithSize:(CGSize)size{
    if (self = [super initWithSize:size]) {
        self.backgroundColor = [SKColor colorWithRed:0.25 green:0.35 blue:0.15 alpha:1.0];
    }
    return self;
}

Since you are using UIKit views, you need to add the -(void) didMoveToView:(SKView *)view method. This method defines and configures the backButton and tableView, places a title label for the view, allocates and initializes the levelsArray and the levelsDescriptionArray, and adds the tableView to the main view. The backButton can be configured as following:

  _backButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
  _backButton.frame = CGRectMake(CGRectGetMidX(self.frame)-100, CGRectGetMaxY(self.frame)-100, 200, 70.0);
  _backButton.backgroundColor = [UIColor clearColor];
  [_backButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal ];
  UIImage *buttonExitImageNormal = [UIImage imageNamed:@"back.png"];
  UIImage *strechableButtonExitImageNormal = [buttonExitImageNormal stretchableImageWithLeftCapWidth:12 topCapHeight:0];
  [_backButton setBackgroundImage:strechableButtonExitImageNormal forState:UIControlStateNormal];
  [_backButton addTarget:self action:@selector(moveToHome) forControlEvents:UIControlEventTouchUpInside];
  [self.view addSubview:_backButton];

Additionally, you must create the moveToHomemethod and import the MyScene.h.

-(void) moveToHome{
    MyScene* myScene = [[MyScene alloc] initWithSize:CGSizeMake(CGRectGetMaxX(self.frame), CGRectGetMaxY(self.frame))];
    [self removeUIViews];
    [self.scene.view presentScene:myScene];
}

Since you need to remove UIKIt views in more than one place, let’s create a method that does exactly that. The method is called removeUIViews and is shown below:

-(void)removeUIViews{
    [_backButton removeFromSuperview];
    [_tableView removeFromSuperview];
}

The label to this interface is very simple. Try to program it yourself. If you have any problems, the following snippet will help you.

  SKLabelNode *titleLabel = [SKLabelNode labelNodeWithFontNamed:@"Chalkduster"];
  titleLabel.text = @"Level Select!!";
  titleLabel.fontSize = 60;
  titleLabel.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame)+300);
  [self addChild:titleLabel];

Step 3

The tableView configuration is a bit tricky since we need to configure several properties, like frame size and location, dataSource, and a delegate.

  _tableView = [[UITableView alloc] initWithFrame:CGRectMake(CGRectGetMidX(self.frame)-150, CGRectGetMidY(self.frame)-250, 300, 400)];
  _tableView.dataSource = self;
  _tableView.delegate = self;

The second and third line of the aforementioned snippet requires an additional step since you are defining simultaneously two views. The data source of the UITableView is self-defined and the UITableView has an action delegate. In LevelSelect.h you should extend your class with UITableViewDataSource and UITableViewDelegate. Your LevelSelect.h should look like:

  @interface LevelSelect : SKScene < UITableViewDataSource, UITableViewDelegate >

Since you are extending the UITableViewDataSource and UITableViewDelegate, additional methods need to be implemented, namely:

  1. -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
  2. -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

The first is only used to know in real time the number of rows existing in the table view. The second method is complex, since it’s used to populate and configure the table view. The table view configuration covers the title, description, and a row image. To use the description in every row, we must initialize each cell with the UITableViewCellStyleSubtitle cell style.

This method is responsible for an additional step: it verifies the current player’s level and disables the levels ahead of the actualPlayerLevel. The full methods declaration can be seen below:

  -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    NSString *levels = [_levelsArray objectAtIndex:indexPath.row];
    NSString *descriptions = [_levelsDescriptionArray objectAtIndex:indexPath.row];
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Identifier"];
    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"Identifier"];
    }
    if (indexPath.row >= actualPlayerLevel)
        [cell setUserInteractionEnabled:FALSE];
    [cell.textLabel setText:levels];
    cell.imageView.image = [UIImage imageNamed:@"appleLogo.png"];
    [cell.detailTextLabel setText:descriptions];
    return cell;
}

 

-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
  return [_levelsArray count];
}

Here are two notes regarding the -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath method. You have not yet initialized the levelsArray, levelsDescriptionArray, and actualPlayerLevel properties. All will be defined in the -(void) didMoveToView:(SKView *)view method. Do not forget to add the actualPlayerLevel property to your class:

@implementation LevelSelect{
  long actualPlayerLevel;
}

Step 4

The levelsArray is defined with the names of the levels. You can call it “Level 1″, “Level 2″, or any other name of your choice. The levelsDescriptionArray follows the same principle, it is a description for each level and can be defined with names of your choice. A possible implementation is:

_levelsArray = [[NSArray alloc] initWithObjects:
                    @"Level 1.",
                    @"Level 2.",
                    @"Level 3.",
                    @"Level 4.",
                    @"Level 5.",
                    @"Level 6.",
                    @"Level 7.",
                    @"Level 8.",
                    @"Level 9.",
                    nil];
  _levelsDescriptionArray = [[NSArray alloc] initWithObjects:
                               @"The adventure begins.",
                               @"A new step.",
                               @"Achivements?!",
                               @"Level 4 description",
                               @"Level 5 description",
                               @"Level 6 description",
                               @"Level 7 description",
                               @"Level 8 description",
                               @"Level 9 description",
                               nil];

Finally, the actualPlayerLevel is a long value type that represents the level of the player. For now, say that the current level is 1.

  actualPlayerLevel = 1;

The -(void) didMoveToView:(SKView *)view method ends when you add the table view to the screen:

  [self.view addSubview:_tableView];

Lastly, you need an additional change in the MyScene.m-(void) moveToGame method. You must call this new class instead of the old one. It can be easily achieved through:

  -(void) moveToGame{
    LevelSelect* factsScene = [[LevelSelect alloc] initWithSize:CGSizeMake(CGRectGetMaxX(self.frame), CGRectGetMaxY(self.frame))];
    // Same code
    // ...
}

At this point you should Run the project and test the new interface. You should see something similar to the next image:

Image1
Illustration of the Level Select Screen

2. Facts Interface

Step 1

The facts interface is where the real action occurs. The interface has several views that directly translates to properties, such as the number of lives remaining, current level, a timer, and true and false buttons. Moreover, for this class you will create a custom initializer. The advantage of this custom initializer is that we can progress through the game and values regarding the level. Also, lives are passed to the class and the class reacts (parses data) accordingly.

Once again, we will use SKLabelNode, UIButtons, and a NSMutableArray. The complete FactsScene.h is the following:

@interface FactsScene : SKScene{
    NSMutableArray* heartArray;
}
@property (nonatomic,weak) SKLabelNode* currentLevelLabel;
@property (nonatomic,weak) SKLabelNode* timerLevel;
@property (nonatomic, retain) UIButton* trueButton;
@property (nonatomic, retain) UIButton* falseButton;
-(id) initWithSize:(CGSize)size inLevel:(NSInteger)level withPlayerLives:(int)lives;

It is now time to move to the FactsScene.m and implement a few objects. You need additional objects to retrieve and store the data received by the initializer. Plus, you need to store the maximum time that a player has to answer each question. Modify the implementation file accordingly.

@implementation FactsScene{
    NSUserDefaults* defaults;
    NSString* musicPath;
    NSInteger playerLives;
    NSInteger playerLevel;
    int maximumTime;
}

Now, you must write the initializer and store its values. The custom initializer is defined as a normal initializer and has the same structure. However, it has more properties as parameters. It should look like this:

-(id) initWithSize:(CGSize)size inLevel:(NSInteger)level withPlayerLives:(int)lives{
    if (self = [super initWithSize:size]) {
        self.backgroundColor = [SKColor colorWithRed:0.35 green:0.25 blue:0.5 alpha:1.0];
        defaults = [NSUserDefaults standardUserDefaults];
        playerLives = lives;
        playerLevel = level;
        maximumTime = 30;
    }
    return self;
}

Step 2

For now, the maximumTime is 30 seconds, but in the future the value will change to 60 seconds (or any other time of your choice). Now in the -(void) didMoveToView:(SKView *)view add a background image, front image, the player’s lives, a timer, true and false buttons, and the current and total level’s questions. For the background and front image the code is simple and you should be able to do it easily (using SKSpriteNode).

    SKSpriteNode *background = [SKSpriteNode spriteNodeWithImageNamed:@"background.png"];
    background.position = CGPointMake(CGRectGetMidX(self.frame),CGRectGetMidY(self.frame));
    background.size = CGSizeMake(768, 1024);
    [self addChild:background];
    SKSpriteNode *frontImage = [SKSpriteNode spriteNodeWithImageNamed:@"transparentCenterBorder.png"];
    frontImage.position = CGPointMake(CGRectGetMidX(self.frame),CGRectGetMidY(self.frame));
    frontImage.size = CGSizeMake(600, 450);
    [self addChild:frontImage];

The player’s lives are represented with a heart image. Since you will declare three lives, you must put three hearts in the screen. You will also use a NSMutableArray since we need to alter its size dynamically. The following snippet will help you:

  heartArray = [[NSMutableArray alloc] init];
  for(NSInteger i = 0; i < playerLives; i++){
    SKSpriteNode* liveImage = [SKSpriteNode spriteNodeWithImageNamed:@"hearth.png"];
        liveImage.scale = .6;
        liveImage.position = CGPointMake(CGRectGetMaxX(self.frame)-40-(i*50),CGRectGetMaxY(self.frame)-40);
        [heartArray insertObject:liveImage atIndex:i];
        [self addChild:liveImage];
  }

The true and false buttons are configured as:

_trueButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    _trueButton.frame = CGRectMake(CGRectGetMidX(self.frame)-350, CGRectGetMidY(self.frame)+300, 335, 106);
    _trueButton.backgroundColor = [UIColor clearColor];
    [_trueButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal ];
    UIImage *buttonTrueImageNormal = [UIImage imageNamed:@"trueBtn.png"];
    UIImage *strechableButtonTrueImageNormal = [buttonTrueImageNormal stretchableImageWithLeftCapWidth:12 topCapHeight:0];
    [_trueButton setBackgroundImage:strechableButtonTrueImageNormal forState:UIControlStateNormal];
    [_trueButton addTarget:self action:@selector(touchWillProduceASound) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:_trueButton];
    _falseButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    _falseButton.frame = CGRectMake(CGRectGetMidX(self.frame)+10, CGRectGetMidY(self.frame)+300, 335, 106);
    _falseButton.backgroundColor = [UIColor clearColor];
    [_falseButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal ];
    UIImage *buttonFalseImageNormal = [UIImage imageNamed:@"falseBtn.png"];
    UIImage *strechableButtonFalseImageNormal = [buttonFalseImageNormal stretchableImageWithLeftCapWidth:12 topCapHeight:0];
    [_falseButton setBackgroundImage:strechableButtonFalseImageNormal forState:UIControlStateNormal];
    [_falseButton addTarget:self action:@selector(touchWillProduceASound) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:_falseButton];

Note that both buttons call the touchWillProduceASound method. That method tests if a given answer is correct or incorrect. In this part, we only use one sound event (the false one).

-(void) touchWillProduceASound{
    long soundFlag = [defaults integerForKey:@"sound"];
    NSString* answer = @"False";
    if (soundFlag == 1){
        SKAction* sound;
        if ([answer isEqualToString:@"False"]) {
            sound = [SKAction playSoundFileNamed:@"wrong.mp3" waitForCompletion:YES];
            NSLog(@"inside");
        }
        [self runAction:sound];
    }
}

Step 3

The game timer is a SKLabelNode that changes at every second. However, its initialization is done as a simple SKLabelNode:

_timerLevel = [SKLabelNode labelNodeWithFontNamed:@"Chalkduster"];
    _timerLevel.text = @"30";
    _timerLevel.fontSize = 70;
    _timerLevel.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame)+350);
    [self addChild:_timerLevel];

To update the label, you need to create a SKAction that defines a custom timer to call a custom method. Then we must create a SKAction sequence:

  SKAction *wait = [SKAction waitForDuration:1];
  SKAction *updateTimer = [SKAction runBlock:^{
    [self updateTimer];
  }];
  SKAction *updateTimerS = [SKAction sequence:@[wait,updateTimer]];
  [self runAction:[SKAction repeatActionForever:updateTimerS]];

You will see a warning regarding the - (void)updateTimer method because you haven’t created it yet. That method does several actions simultaneously taking in consideration several properties:

  • Checks if the sound is on
  • Updates the maximumTime property and Label, decreasing by one value each second
  • Checks the maximumTime, and if the value is zero, it will either end the game or change to another question (more on this topic in the next tutorial)

We advise you to try to write the method using the aforementioned pseudo-code. But if you have trouble, the full method is presented below:

- (void)updateTimer{
    maximumTime--;
    if (maximumTime == 0){
        long soundFlag = [defaults integerForKey:@"sound"];
        if (soundFlag == 1){
            SKAction* sound;
            sound = [SKAction playSoundFileNamed:@"beep.mp3" waitForCompletion:YES];
            [self runAction:sound];
        }
        if (playerLives < 1){
            SKTransition* transition = [SKTransition fadeWithDuration:2];
            MyScene* myscene = [[MyScene alloc] initWithSize:CGSizeMake(CGRectGetMaxX(self.frame), CGRectGetMaxY(self.frame))];
            [self removeUIViews];
            [self.scene.view presentScene:myscene transition:transition];
        } else{
            // other
        }
    }
    [_timerLevel setText:[[NSNumber numberWithInt:maximumTime] stringValue]];
}

Step 4

One more method is missing, the removeUIViews. It removes the UIKit views from the view when a transition occurs.

-(void)removeUIViews{
    [_trueButton removeFromSuperview];
    [_falseButton removeFromSuperview];
}

It is now time to Run the project and see the Facts screen!

Image2
Illustration of the Facts Screen

3. Property Lists

Now it is time to add some data to the app. Go to File -> New -> File and choose the Property List (plist) file. Name it “LevelDescription” and configure it as follows:

Image3
Illustration of the Property List

In order to avoid putting all the data in the plist file, you can download the file directly on the zip file (beginning of the page). This tutorial does not cover in depth the data parsing, so in order to parse that file, the following snippet is used. If you have any doubt, use the comment box at the bottom of the page.

NSString* plistPath = [[NSBundle mainBundle] pathForResource:@"LevelDescription" ofType:@"plist"];
NSMutableDictionary* dictionary = [[NSMutableDictionary alloc] initWithContentsOfFile:plistPath];
  if ([dictionary objectForKey:@"Questions" ] != nil ){
    NSMutableArray *array = [dictionary objectForKey:@"Questions"];
    for(int i = 0; i < [array count]; i++){
      NSMutableDictionary *questions = [array objectAtIndex:i];
      NSLog(@"ID %@", [questions objectForKey:@"id"]);
      NSLog(@"%@", [questions objectForKey:@"statement"]);
      NSLog(@"%@", [questions objectForKey:@"isCorrect"]);
      NSLog(@"%@", [questions objectForKey:@"additionalInfo"]);
      }
    }

Now, Run the project and watch the console logs as you enter the Facts view. Note that the plist file can be configured in several different ways. If you want, you can change the Dictionary, Array types, and configurations. Note that changes must be declared in the parsing cycle. We strongly advise you to play a bit with plists file and the inherent data parsing.


Conclusion

At this point you should be able to use and configure a UITableView, interact between SpriteKit and UIKit frameworks, create SKTransitions and SKActions, and create and parse Property files. In the final section of this series, you will learn about Game Logic.

Android SDK: Running & Debugging

$
0
0

We have been learning how to develop Android apps in this series. In the last tutorial, we looked at connecting hardware and virtual devices to Eclipse. In this tutorial, we will explore running and debugging apps on physical devices and AVDs from Eclipse.


Introduction

For those who have been following this series on Android app development, the app we created earlier doesn’t do much at the moment, but we can use it to work through the process of running apps as you develop, as well as introducing some of the Eclipse ADT utilities you will use for debugging once your apps become more advanced. When you have completed this tutorial, you may wish to spend some time making adjustments to the code in the app we created, and then run it on a physical or virtual device. This tutorial will help you get into the routine of using devices during development and running your apps regularly, so that you catch errors as you code.


1. Running

Step 1

When you compile and run your Android app on a virtual or physical device, Eclipse handles most of the details for you. Eclipse and the ADT create an APK file for your app and install it onto the device you are running. APK files are ultimately what the user downloads from Google Play. However you need to carry out additional steps to build your apps for release, as we will explore later in the series. Initially, Eclipse will build an APK for debugging, which you can run directly on a device from within the IDE.

Connect a hardware device to your computer or start an AVD using the techniques we covered in the last tutorial. We will run the app on whichever device you connect. Any virtual or actual device must meet the minimum API level you specified in the app Manifest or you will not be able to run it.

Step 2

Now we can run the app by first creating a run configuration for it. In Eclipse, choose “Run” then “Run Configurations”. To the left of the Run Configurations window, you will see a list of application types you can run. Select “Android Application” and click the New button above it.

Run Configurations

In the new configuration section that opens, type a name in the Name field, replacing the existing text. This should identify your app at a glance. Click the “Browse” button, select your app project, and click “OK”.

Select App

Click the “Target” tab. You can let Eclipse automatically pick a device to launch the app on, or set it to prompt you to make a choice each time you run the app. This is only applicable when you have more than one device connected to Eclipse, for example a hardware device and an AVD.

Target Tab

Notice that your app is now listed in the Android Application section of the Run Configurations list. You can launch it from here in the future even when you have other apps in your workspace.

Click “Run”. If you set the run config to prompt you to pick a device, Eclipse will do so now. Select the physical or virtual device you are using. If you do not have a device connected or AVD running but have Eclipse set to pick a device automatically, it will launch a suitable one of your AVDs now. You can use the “Run” button in the Eclipse toolbar to launch whichever app you ran last without having to go through the Run Configurations window each time.

Tip: In the Run Configuration Target tab for your app, if you scroll down you will see a section for emulator options, including a command line field. See the Developer Guide for a full list of command line parameters you can supply when using an AVD.

Step 3

When you run your app, Eclipse copies the APK to the device, installs it, and starts the main Activity.

App Launched

Remember the basic user interaction we implemented with the button; clicking it changes the text displayed (clicking with the mouse on the AVD emulates tapping with the finger on a real device).

Button Clicked

Step 4

When you are developing your apps, you will likely repeatedly run them, make edits, and run them again. One of the main tools you will find useful is the Log. Within your Java files, you can write messages out to the LogCat to help with development and debugging. In your main Activity class, add the following instance variable at the top of the class:

private final String LOG_TAG = "MainActivity";

This is a tag constant we will use to write log messages out, using the class name makes it clear which class a log message is from. In the onClick method, just before setting the text on the button, add the following code:

Log.v(LOG_TAG, "button clicked");

You will need the “android.util.Log” import in your class. When you write to the Log, you can choose from various methods to reflect the purpose of the message. In the code above, we use v for verbose. You can also use d for debug messages, i for information, w for warning, and e for error.

Save your file and run the app again using the “Run” button. Make sure you have the LogCat View open in Eclipse. Click the UI button on your device or AVD again. Scroll through the Log messages in the LogCat View until you find your message.

Messages in Log

As you can see the messages are color-coded to reflect the Log method used in each case. You can search for messages by typing into the text-field, which can be particularly useful when there are a lot of messages displayed, for example when you are using a hardware device.

Search LogCat
Tip: If you find that Eclipse hangs or crashes when you use the LogCat View, browse to “Window”, “Preferences”, “Android”, then “LogCat” and set a maximum number of LogCat messages to buffer. If this doesn’t help, reduce the number and try again.

2. Testing

We won’t go into the details of testing in this tutorial as it’s really a topic for later on in your Android learning process. When you are ready to start testing, you can create a test project for your app in Eclipse. See the Developer Guide Testing Fundamentals and Activity Testing Tutorial pages for a comprehensive guide to testing on Android. The testing tools are based on JUnit, with dedicated Android testing resources extending JUnit specifically for Android development. If you are already familiar with Java testing, you should know most of what you need to for Android app testing.


3. Debugging

Step 1

Although you will not need to engage in debugging apps straight away, we will introduce what you can do with the DDMS (Dalvik Debug Monitor Server) as the tools can prove useful throughout the development process. We have already seen one of the debugging Views in Eclipse, the LogCat, but there are several others you can use.

With a hardware or virtual device running and connected to Eclipse, open the DDMS perspective by choosing “Window”, “Open Perspective”, and “DDMS”. You can toggle between this and the Java perspective using the buttons you see at the top right corner of Eclipse.

Step 2

Let’s explore some of the DDMS Views. We met the Devices View last time (it displays a list of connected devices together with links to any processes running on them). Selecting a process gives you access to the buttons in the Devices View. Find yours in the list by looking for the package name.

App Process

With your process selected, click the “Update Threads” button in the Devices View to populate the Threads View.

Thread Updates

The “Update Heap” button has the same effect for the Heap View. You will get to know the other Views as you need to for the apps you develop, some of them are relevant only to apps carrying out particular types of task. For now, just take a moment to notice a couple of aspects of the DDMS worth bearing in mind.

The Emulator View provides control over any running instances of virtual devices as you will see if you select an AVD in the Devices list and open the Emulator Control tab. Also, note that you can stop a running process in the Devices View, debug a running process, and force garbage collection. Before we finish looking at the DDMS, with your app visible on the screen of a hardware or virtual device, select the device in the Devices View and click the “Screen Capture” button.

Screen Capture Button

An image of your device appears in a new window. From here you can save or copy the image to use in your promotional listings for the app, clicking Refresh to update the screen capture.

Screen Capture Window

For additional tips on debugging your Android apps, see the Developer Guide.


Conclusion

When you start creating Android apps, your primary concerns will relate to running your apps and monitoring their behavior through logging messages to the console. However, as your projects become more complex and when you do get to the stage of preparing your apps for release, you will find the debugging and testing tools for Android in Eclipse indispensable. In the next part of this series, we will introduce the Android Activity lifecyle, which is vital to understand before you can start to create fully functional apps.


iOS SDK: Build a Facts Game – Game Logic

$
0
0

Welcome back to the third and final section of our Facts Game with Sprite Kit tutorial series. This tutorial will teach you how to use the Sprite Kit framework to create a question-based facts game. It is designed for both novice and advanced users. Along the way, you will apply the Sprite Kit core.


Introduction

In this tutorial, you will program the entire game logic including the player’s life, the question, and the player’s answer. This tutorial series is broken up into three sections: Project Setup, Facts Interface, and Game Logic. If you haven’t yet completed the second section, you can download the project and pickup exactly where we left off. Each part produces a practical result, and the sum of all parts will produce the final game. Despite the fact that each part can be read independently, for a better understanding we suggest to follow the tutorial step by step. We also included the source code for each part separately, thus providing a way to start the tutorial in any part of the series.

This is what our game will look like upon completion:

Image0
Illustration of Final Result – Facts

1. Custom Facts Class

In the last tutorial, you defined a plist file for the questions. Each question has four properties. In order to manage them, you need to create a custom class to afford that task properly. Therefore, you need to form another Objective-C class. Name it factObject and define the NSObject superclass.

Now, let’s edit the header file and add the four plist properties. Each plist property has its own features:

  • The statement Id is an int.
  • The statement is a NSString.
  • The isCorrect statement is an int.
  • The additional information is a NSString.

The end result should be similar to this:

  @property(nonatomic,readwrite) int factID;
  @property(nonatomic,readwrite,retain) NSString *statement;
  @property(nonatomic,readwrite) NSInteger isCorrect;
  @property(nonatomic,readwrite,retain) NSString *additionalInfo;

You don’t need to use the implementation file (.m). We will parse the plist file to this custom class and use the values directly from the memory.


2. Facts Interface: Initialization

In the last tutorial, you defined the basic structure of the facts interface. It is now time to complete it with the logic steps. To complete this game, we need to create a question label, a customized background statement, a button that asks for another question, and a true and false interface. Those four statements translate into five properties defined in the FactsScene.h file. Once again, you can name them as you please. Our implementation is:

  @property (nonatomic, retain) UILabel *questionLabel;
  @property (nonatomic, retain) SKSpriteNode *backgroundStatement;
  @property (nonatomic, retain) UIButton *nextQuestion;
  @property (nonatomic, retain) SKSpriteNode* wrong;
  @property (nonatomic, retain) SKSpriteNode* correct;

Now move your attention to the FactsScene.m. You need to define several objects that are used internally in the class:

  • A NSMutableArray to store the questions
  • A random value that represents a random question
  • The question identifier
  • The minimum threshold for the right questions; this threshold indicates the minimum required correct answers for the user to advance to another level. In this tutorial, you will use value seven.

Your implementation file should look like this:

  NSMutableArray *statements;
  int randomQuestion;
  int questionNumber;
  int totalRightQuestions; // need 7 out of 10 to pass to the next level

It is now time to allocate a few values and begin with the logic. In the -(id) initWithSize:(CGSize)size inLevel:(NSInteger)level withPlayerLives:(int)lives method initiate the questionNumber and the totalRightQuestions. Since it is the first time you use it, the initiation is easy and can be done like:

        questionNumber = 1;
        totalRightQuestions=0;

Now it is time to use the custom class defined in the aforementioned step. Parse the plist file and use the information store in the plist to allocate and populate new factObject objects. Note that we will store each factObject object in a custom NSMutableArray already defined (statements). The complete snippet is below.

        statements = [[NSMutableArray alloc] init];
        NSString* plistPath = [[NSBundle mainBundle] pathForResource:@"LevelDescription" ofType:@"plist"];
        NSMutableDictionary* dictionary = [[NSMutableDictionary alloc] initWithContentsOfFile:plistPath];
        if ([dictionary objectForKey:@"Questions" ] != nil ){
            NSMutableArray *array = [dictionary objectForKey:@"Questions"];
            for(int i = 0; i < [array count]; i++){
                NSMutableDictionary *questions = [array objectAtIndex:i];
                factObject *stat = [factObject new];
                stat.factID = [[questions objectForKey:@"id"] intValue];
                stat.statement = [questions objectForKey:@"statement"];
                stat.isCorrect = [[questions objectForKey:@"isCorrect"] integerValue];
                stat.additionalInfo = [questions objectForKey:@"additionalInfo"];
                [statements addObject:stat];
            }
        }

This step removes the older parsing code from the -(void) didMoveToView:(SKView *)view method. You can remove it, since you will not use it anymore.


3. Facts Interface: Logic

It is now time to focus on the logic code itself. We need to show the question to the user. However, the question is always a random choice. Start to define a rectangle to afford the question and then allocate the necessary resources for the question’s text. The following snippet will help you:

    CGRect labelFrame = CGRectMake(120,300, 530, 100);
    _questionLabel = [[UILabel alloc] initWithFrame:labelFrame];
    randomQuestion = [self getRandomNumberBetween:0 to:([statements count]-1)];
    NSString *labelText = [[statements objectAtIndex:randomQuestion] statement];
    [_questionLabel setText:labelText];
    [_questionLabel setTextColor:[UIColor whiteColor]];
    [_questionLabel setFont:[UIFont fontWithName:NULL size:23]];
    [_questionLabel setTextAlignment:NSTextAlignmentCenter];
    // The label will use an unlimited number of lines
    [_questionLabel setNumberOfLines:0];

Note that you will not use the SKLabelNode over the simple NSString because of a SKLabelNode limitation; it is for single-line text only. A warning will appear regarding the getRandomNumberBetween:0 to:X method. You need to declare and code it; its objective is to return a random value between two values. The next snippet will help you:

-(int)getRandomNumberBetween:(int)from to:(int)to {
    return (int)from + arc4random() % (to-from+1);
}

Now that you can see the question, we need to add some functionalities to the right and wrong button. Change both selectors and call a new method called: presentCorrectWrongMenu.

[_falseButton addTarget:self action:@selector(presentCorrectWrongMenu:) forControlEvents:UIControlEventTouchUpInside];
[_trueButton addTarget:self action:@selector(presentCorrectWrongMenu:) forControlEvents:UIControlEventTouchUpInside];

Additionally, define a tag for each button. The true button will be tag = 1 and the false tag = 0. These tags help you when you call the -(void)presentCorrectWrongMenu:(UIButton*)sender method to determine which button was tapped to call that same method.

  [_trueButton setTag:1];
  [_falseButton setTag:0];

The next step is to add the -(void)presentCorrectWrongMenu:(UIButton*)sender method. This method is complex and recognizes which button is tapped, adds a custom answer interface, and adds a button that calls the next question. Use the following snippet to achieve the above-mentioned topics:

-(void)presentCorrectWrongMenu:(UIButton*)sender{
    int userData = sender.tag;
    // background
    _backgroundStatement = [SKSpriteNode spriteNodeWithImageNamed:@"background.png"];
    _backgroundStatement.position = CGPointMake(CGRectGetMidX(self.frame),CGRectGetMidY(self.frame));
    _backgroundStatement.size = CGSizeMake(768, 1024);
    _backgroundStatement.zPosition = 10;
    _backgroundStatement.alpha = 0.0;
    [self addChild:_backgroundStatement];
    _nextQuestion = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    _nextQuestion.frame = CGRectMake(CGRectGetMidX(self.frame)-100, CGRectGetMidY(self.frame)+90, 200, 70.0);
    _nextQuestion.backgroundColor = [UIColor clearColor];
    [_nextQuestion setTitleColor:[UIColor blackColor] forState:UIControlStateNormal ];
    [_nextQuestion setTitle:@"Tap Here to Continue" forState:UIControlStateNormal];
    [_nextQuestion addTarget:self action:@selector(nextQuestion) forControlEvents:UIControlEventTouchUpInside];
    _nextQuestion.alpha = 1.0;
    [self.view addSubview:_nextQuestion];
    [_backgroundStatement runAction:[SKAction fadeAlphaTo:1.0f duration:0.2f]];
    _trueButton.alpha = 0.0;
    _falseButton.alpha = 0.0;

A warning will appear, however do not fix it right away. First, end the method declaration. Now that you have a custom interface for the answer, you need to test the player’s answer. To achieve that, you need to know which button the player tapped and the inherent question’s answer. You already know this, so you only need to create a simple logic test condition. To do this, you need to test if the answer is correct or incorrect, play a sound accordingly, and proceed to the properties update. The next snippet will help you. Note that you must place it where the last snippet of code ended.

if( ([[statements objectAtIndex:randomQuestion] isCorrect] == 0 && userData == 0) || ([[statements objectAtIndex:randomQuestion] isCorrect] == 1 && userData == 1) ){
        if ([[statements objectAtIndex:randomQuestion] isCorrect] == 0)
            _questionLabel.text = [[statements objectAtIndex:randomQuestion] additionalInfo];
        _correct = [SKSpriteNode spriteNodeWithImageNamed:@"correct.png"];
        _correct.scale = .6;
        _correct.zPosition = 10;
        _correct.position = CGPointMake(CGRectGetMidX(self.frame),800);
        _correct.alpha = 1.0;
        totalRightQuestions++;
        [self touchWillProduceASound:@"True"];
        [self addChild:_correct];
    }
    else{
        if ([[statements objectAtIndex:randomQuestion] isCorrect] == 0)
            _questionLabel.text = [[statements objectAtIndex:randomQuestion] additionalInfo];
        _wrong = [SKSpriteNode spriteNodeWithImageNamed:@"wrong.png"];
        _wrong.scale = .6;
        _wrong.zPosition = 10;
        _wrong.position = CGPointMake(CGRectGetMidX(self.frame),800);
        _wrong.alpha = 1.0;
        [self removePlayerLife];
        [self touchWillProduceASound:@"False"];
        [self addChild:_wrong];
    }
}

Do you remember the last warning? Now you should see several warnings. Don’t worry, they’re warning you that several methods are missing. We can correct that. The first method to define is the -(void)nextQuestion. As the name suggests, it calls the next question. Besides presenting a new question, it resets the timer, increments the question number, updates the current question label, removes the presented question from the array, and tests the logic needed to move to another level. The complete source code of -(void)nextQuestion is:

-(void)nextQuestion{
    [self resetTimer];
    questionNumber++;
    _currentLevelLabel.text = [[NSString alloc] initWithFormat:@"Level: %ld of 10", (long)questionNumber];
    _wrong.alpha = 0.0;
    _correct.alpha = 0.0;
    _backgroundStatement.alpha = 0.0;
    _nextQuestion.alpha = 0.0;
    [statements removeObject:[statements objectAtIndex:randomQuestion]];
    //random question
    randomQuestion = [self getRandomNumberBetween:0 to:([statements count]-1)];
    [_questionLabel setText:[[statements objectAtIndex:randomQuestion] statement]];
    _trueButton.alpha = 1.0;
    _falseButton.alpha = 1.0;
    if (questionNumber == 10 && totalRightQuestions > 7){
        int nexLevel = playerLevel+2;
        [defaults setInteger:nexLevel forKey:@"actualPlayerLevel"];
        [self removeUIViews];
        SKTransition* transition = [SKTransition doorwayWithDuration:2];
        LevelSelect* levelSelect = [[LevelSelect alloc] initWithSize:CGSizeMake(CGRectGetMaxX(self.frame), CGRectGetMaxY(self.frame))];
        [self.scene.view presentScene:levelSelect transition:transition];
    }
}

Note that you hard-coded the maximum questions (10) for this level and the threshold for the next level (7). Once again, a new warning will appear. No resetTimer method exists; this method only resets the maximumTime property to 60 and updates the label accordingly:

-(void)resetTimer{
    maximumTime = 60;
    [_timerLevel setText:@"60"];
}

In the last tutorial, you defined the touchWillProduceASound method. However in this tutorial, you need to modify it further. The objective is to pass it a object that represents the correct or incorrect answer. Then the corresponding sound will play. The complete method is:

-(void) touchWillProduceASound:(NSString*)answer{
    long soundFlag = [defaults integerForKey:@"sound"];
    if (soundFlag == 1){
        SKAction* sound;
        if ([answer isEqualToString:@"False"]) {
            sound = [SKAction playSoundFileNamed:@"wrong.mp3" waitForCompletion:YES];
        } else {
            sound = [SKAction playSoundFileNamed:@"right.mp3" waitForCompletion:YES];
        }
        [self runAction:sound];
    }
}

You still need to define the -(void)removePlayerLife method. As the name states, it tests the life of a player and acts accordingly. If the player has more than one life, a life is reduced and the inherent asset is updated or is moved to the home screen. The complete method is below.

-(void)removePlayerLife{
    if (playerLives > 1){
        for(NSInteger i = 0; i < playerLives; i++){
            SKSpriteNode* node = [heartArray objectAtIndex:i];
            if (i == (playerLives-1)){
                node.alpha = .1;
            }
        }
        playerLives--;
    } else {
        [self moveToHome];
    }
}

At this point, we’re nearly finished. It is now time to update the - (void)updateTimer defined in the last tutorial. This new method is responsible for updating the timer value and testing the player’s life. It automatically reacts when the timer hits zero. At that time, it tests the player’s life and acts accordingly. It goes to the main menu if the player’s life is less than one or calls another question otherwise (decreasing the player’s life). The complete snippet is below.

- (void)updateTimer{
    maximumTime--;
    if (maximumTime == 0){
        if (playerLives < 1){
            [self touchWillProduceASound:@"False"];
            [self moveToHome];
        } else{
            [self presentCorrectWrongMenu:_trueButton];
            [self touchWillProduceASound:@"False"];
            [self removePlayerLife];
        }
    }
    [_timerLevel setText:[[NSNumber numberWithInt:maximumTime] stringValue]];
}

4. Additional Methods

Two additional methods were created: -(void)moveToHome and -(void)removeUIViews. We need to define them because we’ll use them more than once. It is good practice to reuse code instead of typing it all again. The -(void)moveToHome is just a call to a SKTransition and MyScene class. The code is:

-(void)moveToHome{
    SKTransition* transition = [SKTransition fadeWithDuration:2];
    MyScene* myscene = [[MyScene alloc] initWithSize:CGSizeMake(CGRectGetMaxX(self.frame), CGRectGetMaxY(self.frame))];
    [self.scene.view presentScene:myscene transition:transition];
}

The -(void)removeUIViews removes the UIKit views from the superview. Here is what the code looks like:

-(void)removeUIViews{
    [_trueButton removeFromSuperview];
    [_falseButton removeFromSuperview];
    [_questionLabel removeFromSuperview];
}

Now that everything is correct, Run the project. Every time you correctly answer a question, you will see an interface similar to the next image:

Image1
Illustration of a correct answer

On the other hand, when you incorrectly answer a question, you will see an interface that looks like this:

Image2
Illustration of an incorrect answer

5. Final Improvements

There’s just one more step before we’re done. We need to correctly initialize the actualPlayerLevel at the level selection. Switch your attention to the MyScene.m class (the first one created by the Xcode) and let’s add some lines of code. Initially, add an object of the type NSUserDefaults to the @implementation section. The following snippet will help you:

  @implementation MyScene {
    // code
    NSUserDefaults* defaults;
}

Now inside the -(void) didMoveToView:(SKView *)view, add the inherent NSUserDefaults initialization. The default value is one, so that a new player always starts a new game at Level 1. Moreover, if the player didn’t achieve the minimum requisites to pass the level, it starts again at that same level. The result is below.

    defaults = [NSUserDefaults standardUserDefaults];
    [defaults setInteger:1 forKey:@"actualPlayerLevel"];
    //more code..

Several other adjustments can be made to this game. You can customize the correct answer rates for questions, animations, and transitions, or alter the landscape and portrait mode. We think that you are ready for such a task. Try to implement them on your own.


Conclusion

At the end of this Facts tutorial, you should be able to create a SpriteKit game, create and configure several SpriteKit views and actions, configure several UIKit views, use them in parallel with SpriteKit, and parse Property lists. Don’t hesitate to use the comment section below for suggestions or comments. Thanks for reading!

Android SDK: Activities & Lifecycle

$
0
0

We are learning to develop Android apps from scratch in this series. We already encountered the basics of developing, running, and working with your apps in Eclipse, as well as looking at the essential elements in any app project. In this tutorial, we will explore the Activity life cycle, which is one of the key aspects of Android you need to understand to start making apps. We will look at the Activity life cycle for a typical app launched from the device menu in this tutorial.


Introduction

The Activity life cycle doesn’t just come into play when the user runs your app, it also affects what happens when the user switches away from and back to your app. When you develop an app, you need to remember that the user will typically navigate between it and other apps during execution. An app can either be in the foreground or the background depending on what the user is doing. Your apps need to be able to cope with this, saving and restoring data when necessary. Keep in mind that the process is slightly different for some apps, like widgets.


1. Callback Methods

Step 1

To control what happens when your Activity is in different states, for example when the user navigates away from or back to it, you can implement various methods. These are the Activity life cycle callback methods. Android calls these methods when your Activity enters each state, so you can take steps to ensure the app continues to function, does not lose data, and does not use unnecessary resources when the user is not interacting with it. Each callback method puts your app in one of a range of possible states.

If you’ve ever programmed Java applications before, you know that Android apps are launched differently. Rather than using a main method, when your app is launched the onCreate method of the main Activity class executes. Remember that we specified the class in the Manifest as the main launcher Activity. The onCreate method is the first of the Activity callbacks, which executes when the user launches your app. The onCreate method puts your app in the Created state.

The diagram in the Developer Guide provides an intuitive representation of the life cycle, callback methods, and states. The Resumed state, which represents your app running as the user interacts with it, follows the onResume method. Various callback methods take your app towards and away from the Resumed state, starting and stopping it.

For most apps you only need to implement some of the callback methods, at the very least onCreate. However, understanding all of the callbacks and states will help you to grasp what happens on the Android system when your app runs and stops running. In general, you need to implement whichever callbacks that let the user resume your app from where they left off, and if they navigate away and back, save any data you need to persist and prevent your app from using resources unnecessarily.

Step 2

There are five states your app can be in: Created, Started, Resumed, Paused, and Stopped. Seven callback methods transition into and out of these states: onCreate, onStart, onRestart, onResume, onPause, onStop, and onDestroy. These methods take your app between the possible states, in some cases very quickly. In general you can think of your app as being either resumed, paused, or stopped at any time, since the other states are transitory.

When your app is running and the user is interacting with it, it is in the Resumed state. Your app goes into Paused state when another Activity is in the foreground but only partially hides it; the user can’t interact with your app in this state. When your app is completely in the background and the user can’t see or interact with it at all, it is in the Stopped state. Here the Activity can retain data in this state but can’t execute.


2. Moving Towards Resumed

As we know, the main Activity starts when the app is launched, with the onCreate method executing, letting you prepare the Activity UI and any data items you need throughout the class. Most apps you build will have more than one Activity in them, with the other Activities launched on user interaction with the app. You can launch one Activity from another using the Intent class as in the following example code:

Intent aboutIntent = new Intent(this, About.class);
startActivity(aboutIntent);

This represents another Activity class named “About” in your app package. You can create a new Activity in Eclipse by selecting your source package and choosing “File”, “New”, “Class”, and selecting the Android Activity class as superclass. Remember that each Activity must be listed in your Manifest. You can also pass data between Activities using the Intent class.

When any Activity runs, the onCreate method executes, so you can treat other Activity classes in your apps similarly to the main Activity except for the way you list them in the Manifest. You can create a layout file for each Activity and set it using the same technique you used for the main Activity.

After the onCreate method of an Activity executes, the onStart and onResume methods execute, placing the Activity in Resumed state, passing through Created and Started along the way.

Your Activities can reach the Resumed state in more than one way, not just when the app is launched. If your Activity is Paused or Stopped, it can be brought back into the foreground without the onCreate method being called again. If your app is brought back into the Resumed state from the Paused state, the Activity onResume method executes. If the app is brought back from Stopped state, onRestart executes, followed by onStart and onResume.


3. Moving Towards Destroyed

Step 1

When your app is either exited or hidden, it moves from Resumed towards being destroyed. The onPause method takes your Activity from its normal running Resumed state to Paused. In onPause, you should stop any ongoing resource-hungry tasks such as animations, sensor handling, and broadcast receivers. If onPause executes, there is a good chance onStop is about to execute too since the user is possibly navigating away from your app. You can also use the method to save data, although in general this is best done in onStop.

As we mentioned above, your Activity can go back from Paused to Resumed via the onResume method. This means that you can use onResume to restore anything you stopped or released in onPause. However, bear in mind that onResume also executes in other cases, such as when the app is launched.

Step 2

After onPause, onStop executes if the app enters Stopped state. From here, onRestart, onStart, and onResume can still take it back to Resumed. In onStop you should carry out any data saving operations you need, such as writing to databases. Make sure you release any resources your app is using in onStop to prevent any memory leaks if your app is destroyed.

The system saves certain data items when your app resumes after it is stopped, such as what is displayed in the Views. When an Activity moves from Stopped back to Resumed, the onRestart, onStart, and onResume methods all execute. However, onStart and onResume execute in other cases, such as when the app is launched. The onRestart method only executes when the app is coming back from Stopped state, so you can use it to reinstate anything you did in onStop.

Tip: When you start one Activity from another in your app, the first Activity enters Stopped state. If the user then uses the back button to go back from the second to the first Activity, the onRestart method of the first Activity executes.

Step 3

If your app is about to completely finish, like with the instance of your current Activity removed from the system, onDestroy executes. Although this is the last method to execute before your Activity disappears completely, you should not typically use it to clean up. You should generally use onStop or onPause for this. One exception to this is where a background thread is running, in which case you should stop it in onDestroy.

After onDestroy executes, if the user navigates back to your app Activity the onCreate method executes again. In general, you can assume that onPause and onStop will execute before onDestroy. However, if you explicitly call the finish method to end an Activity, only onDestroy executes.

In many cases, you don’t need to worry about most of the life cycle callbacks in your apps at all, since you can retain data using the onCreate method parameter. The Bundle parameter to your Activity onCreate method automatically saves View information as we mentioned above. However, you can also use the object to save additional data, such as variables you update as the user interacts with your app. To do this, you can implement the onSaveInstanceState method in an Activity class, writing key value pairs of data you can then retrieve in onCreate.

Tip: When the user changes orientation, switching between portrait and landscape, your Activity is actually recreated, with onCreate executing again. This is known as a configuration change. The system assumes you need to recreate the Activity in case, like if you are using a different layout for each orientation. However, in many cases you will not want this to occur. To avoid your Activity recreating on an orientation change, you can either add the “android:configChanges” attribute to your Activity in the Manifest or can structure your Activity to use Fragments you retain on configuration changes.

Conclusion

The various states and callback methods in Android Activities can be the source of much confusion when you start to learn how to develop apps for the platform. However, in most cases you only need to implement a minimal number of the methods to keep your apps functional and behaving the way users expect. In the next part of the series, we will look at some of the common Android classes you are likely to find useful in your first apps. After that we will look at the Android sample code, what you need to know about releasing your apps, and some other suggestions for future learning.

Android SDK: Common Android Components

$
0
0

In this series we are learning the essential features of Android development that you need to know to start building apps. So far, we’ve looked at the structure and typical elements in an Android app, including user interface elements and data storage. You can use what we covered already to start creating your own apps. But before you do, we will run through some common Android components in this tutorial, then have a quick look at the SDK samples in the next tutorial.


Introduction

There are four main Android app components: activities, services, content providers, and broadcast receivers. Whenever you create or use any of them, you must include elements in the project manifest. We’ve met Activities already so I won’t spend any more time on them, but I will go through the other three main app components. I’ll also mention a couple of resources your apps are most likely to use, including fragments and the action bar.


1. Services

A service in Android is a background process. Services are typically used for processes that are ongoing or that take a significant period of time. A service doesn’t have a user interface, so they are often combined with other components such as activities. A typical example is an app in which an activity starts a service running on user interaction, with the service perhaps uploading data to a web resource. The user can continue to interact with the activity while the service runs because it executes in the background.

Tip: If you want to carry out background processing such as fetching Internet data, you do not necessarily need to implement a service class. Depending on the needs of your application, it may be more appropriate to use an inner AsyncTask class inside your activity. This takes the background processing away from the UI, but your activity can receive the results of the AsyncTask operation to update the UI.

To add a service component to the manifest, use the following syntax with the element placed inside the application element:

<service android:name=".ServiceClassName" />

You can create a service class in Eclipse using the same process you would for an activity, choosing service as the superclass. Services are different from the activity components that we’ve looked at previously, in a number of important ways. If you start a service that runs from an activity and the user navigates away from the activity to another app, the service will continue to run. A service therefore has a different lifecycle to the one we explored for activities. You need to bear this in mind to ensure your apps are efficient.

Other app components can bind to services, requesting and receiving data from them. If a bound service is running, it stops when all of the components that are bound to it stop. Although a service is separate from the app user interface, a service started in an activity will run in the same thread as it. However if your service is going to use a significant amount of processing resources, you can create a separate thread to run it in. For more on services, see the Android Developer Guide.


2. Content Providers

A content provider is a component for managing a data set. This data set can be private to your application or can be shared, with other apps able to query and modify the data. If you create a content provider to manage data for your own app, your UI components such as activities will use the content provider, typically through the content resolver class to interact with the data. When used by other apps, the content provider manages access to the data through standard methods to interact with structured data sets such as databases.

If you are at all familiar with relational databases, you intuitively understand the methods used to access data with a content provider. The content provider presents data in a set of tables with rows and columns, and each column within a row (or record) includes a single data value. Handling data returned through a content provider is therefore similar to handling database query results.

Although you may of course create a content provider app at some point, in your initial apps you are far more likely to access one created by another developer or the Android system itself, for example the device calendar or contacts. Content providers can define permissions that client apps are required to have in order to use them. To use a content provider in your app, you need to add the relevant permissions for it in your manifest.

Tip: If you simply need a structured data source for use within your app, you typically do not need to create a content provider. You can create an SQLite database which is private to your app without the need to use the content provider classes at all. The only occasions in which you need to create a content provider are where you want other apps to access your structured data, where you want to copy structured data from your apps to other apps, or where you want to make use of the search framework.

See the Content Providers section in the Android Developer Guide for more information.


3. Broadcast Receivers

The Android system makes various types of broadcasts an app can respond to. You can also develop apps to make these broadcasts, but this is far less likely than to listen for existing broadcasts, at least for your first apps. System announcements include information about the device’s hardware, such as the battery level, the screen shutting off, the charger being plugged into an outlet, etc.

To receive broadcast announcements on Android, your apps can use a broadcast receiver. A typical example of this is a battery level widget in which you want to update the display when the battery level changes. In this case, you could use a service class in conjunction with a broadcast receiver to let your app keep listening for announcements in the background.

The Android system models broadcast announcements as intents, which can be used to start an activity. An intent is an action that the system performs, such as launching an activity or making an announcement. To use a broadcast receiver, your apps must declare it in the manifest, along with an optional intent filter, indicating the actions you want to receive:

<receiver android:name=".YourReceiver"><intent-filter><action android:name="android.intent.action.BATTERY_LOW" /></intent-filter></receiver>

This applies to a broadcast receiver in which your app can receive the battery low intent. Note that you can’t receive all system announcements by declaring their actions in the manifest in this way. In some cases you need to register to receive them in Java, for example, with the BATTERY_CHANGED action. See the broadcast receiver class for more on this type of app.


4. Other Classes

As we’ve seen, the Android components are designed to provide interaction between apps. Just as broadcast announcements are available to any app on the system, Android provides certain actions you can use to carry out common tasks in your apps, such as dialing a number. Similarly, you can often use functionality provided by other developers to carry out processing, saving on the amount of code you must implement yourself and letting you focus on the unique aspects of your apps. When you launch one intent from another, you can set it up to return a result to the launching activity, even if the intent that is launched is not part of your app. This lets your app continue to function after the requested action is completed.

Other Android components you should be aware of include fragment and the action bar. Let me briefly run through them:

Fragments

Rather than simply using an activity and a layout to define the whole user interface for each app screen, it is often more efficient to use fragments. With fragments, you can divide the parts of your user interface into logical sections and even reuse those sections in more than one screen of your app. This saves you from the task of implementing the same visual/interactive elements more than once and it gives you a single point of change for these sections. Fragments are modeled as part of an activity, so a fragment is tied to the lifecycle of the activity it is in. See the fragment section of the Developer Guide for more.

Action Bar

The action bar is another key user interface element you may find useful. The action bar gives your app a user interface component that is consistent across the Android system, which makes it an intuitive element for the platform’s users. Typical items displayed in the action bar include an indicator of the user’s location within your app if appropriate and shortcuts to common actions including navigation between the parts of the app. To use the action bar in an activity, make sure that your class extends the ActionBarActivity class and apply a AppCompat theme to the activity in the manifest. See the Developer Guide for more information about the action bar.


Conclusion

Which Android classes and components you use naturally depend on what your app does. However, the above components give you an overview of which classes and components you can choose from. It is often difficult to decide which component or class to use for a particular feature or function, so make sure you understand the purpose of each one before you make a decision. In the next few tutorials, we will look at the Android samples and the app publishing process.

Android SDK: Samples

$
0
0

In this series, we have been exploring the basics of Android development. We have looked at what you need to know when building the elements in Android apps. In this tutorial, however, you will see that the Android platform provides resources you can learn from. The samples of the Android SDK include complete applications in which you can see functioning examples of typical Android application components. You can use the samples in more than one way, including directly from within Eclipse.


Introduction

The Android SDK samples include apps performing various types of functionality, including a variety of user interface elements, data management, interaction, demonstrations of using media and connectivity. Even if you do not wish to build the specific types of app you see in the samples, many of them include functionality that is common to many different app types, so the resources are well worth exploring.


1. Installation

Step 1

To use the Android samples directly from within Eclipse, you first need to make sure you have them installed. Select Window then Android SDK Manager. In the package list, you will find the samples inside each API level folder – select the most recent one and expand it. If Samples for SDK is not already installed, select it and install it now.

SDK Samples

Once you have the samples installed, you can use them directly from within Eclipse. Remember that we discovered near the beginning of the series how you can regularly keep your Android SDK tools up to date using the SDK Manager, so you may wish to do this at the same time if there are updates ready.


2. Creating Sample Projects

Step 1

You can create a sample project in Eclipse, letting you see the code within the samples as well as running them on actual or virtual devices. This lets you make use of the algorithms within the samples by copying and pasting from them, or just learn from them, using them as a reference for your own apps. To create a sample project in Eclipse, choose File, New then Project. Expand the Android folder, choose Android Sample Project and click Next.

Sample Project

Choose a build target and click Next.

Build Target

Now you can choose from the list of samples, including the legacy samples, many of which are fully functional apps containing the types of processing your initial apps may need. You can explore the samples in your own time, but to start with, choose the Notepad sample and click Finish.

Notepad Sample

Eclipse will build the app in your workspace as it does with your own app. You should see the Notepad app now in your Package Explorer. Expand the folder for the app so that you can explore its contents.

Sample in Package Explorer

Step 2

You can take your time looking at the various files in the sample project, including the Manifest, the source code, and the resource files, such as the layouts, drawables, values, and menus. The Notepad app is a great resource for finding out about lots of common types of functionality on Android. Start by opening the Manifest file and switching to the XML tab.

Don’t be intimidated by the complexity of the files in the samples. If you explore them using the Eclipse Views, the Outline View in particular, you will see that they have the same overall structure as the simple app we created earlier in this series.

Notepad Manifest

The source files typically include lots of notes as code comments so there is plenty of explanation if you are unsure what a particular code snippet is meant to do. Expand the elements in the Outline View and you will see that the NotesList Activity is listed as main launcher Activity for the app. Since this is the main entry point for the app on the system, it makes a good place to start exploring the app source code.

Step 3

Once you have taken some time to look through the other Manifest contents, open the NoteList Activity class in the src folder of the Notepad app.

As you can see, the source code is well commented, outlining the responsibility of the class as well as explaining the task of each of its methods or parts of a method. Take a look at the onCreate method in the Outline View.

Activity Outline

As you will notice straight away, the code in the onCreate method is slightly different from what we have seen before as this is a ListActivity. You will see a reference to a layout for each item in the list, noteslist_item. Locate the layout in the app’s res layout folder and open it. You can switch between the markup and graphical views of the layout item as we saw earlier.

You can use this general approach to exploring the sample apps, by navigating between the various elements, following references between the source files in a logical way.

Step 4

You can run sample apps on physical devices or AVDs as you would with an app you created yourself. To do so, connect a device or launch an AVD, and browse to Run Configurations. Select Android Application, click the New button, and locate the sample app using the Browse button. As you can see, the process of running a sample app is exactly the same as running your own apps.

If you are developing an app with similar functionality to what is in one of the sample apps, you can keep the sample app open alongside your own app, referring to it as you develop your own algorithms. Apps such as the Notepad sample include handy overviews of typical processes such as handling data via a Content Provider, which you can see in the NotePadProvider class. The samples are designed to showcase how you can implement certain tasks on the Android platform and can therefore be extremely useful as practical demonstrations of what you learn in the Developer Guide.

Tip: When you use the legacy samples in the Android SDK, you will see Eclipse displaying warning messages regarding deprecated code. This happens because the legacy samples were built for previous versions of the SDK. If you plan on using any functionality listed as deprecated in Eclipse, try to find out what the recommended alternatives are for more recent versions of the Android SDK.

Step 5

Feel free to further explore the SDK samples. The content of many samples should be self-explanatory. However, sometimes the contained functionality is not immediately obvious from the sample’s name. One sample worth checking out is the API Demos sample. You can find it in the list as we did with the Notepad app.

Start a sample project with the API Demos sample, expand it in the Package Explorer as we did earlier, and open the src folder. The application is divided into packages for various types of functionality. There is a lot of processing to see and learn from. Open a package to explore the classes it contains. As with the other sample code, the code is well commented to help you understand what each class and method does. The API Demos application includes graphics, animation, media, security, and accessibility functions.


3. Other Ways to Use Samples

Creating sample projects in Eclipse is the easiest and most useful way to learn from the Android SDK sample code. However, there are other ways to use the samples included in the SDK. You can find the files for each sample project in the ADT Bundle directory on your computer. Inside the sdk folder, you will see a folder named samples. Each platform level for which you have installed samples will be listed here with its own dedicated folder. Inside this folder you will see various folders for sample categories. You can browse, open, and interact with the source code files in this way as well.

The Android Developers site Samples section also lets you download and view sample code for the platform. These samples are built to use with Android Studio as Gradle builds. You can download complete projects and import them into Android Studio, letting you interact with their content in the IDE as well as running the apps on an Android device.


Conclusion

The Android samples include a lot of functionality. Although some of the legacy content is a little out of date, there is still plenty you can learn from them. If you are trying something that one of the sample projects already does, you can save yourself a lot of development time simply by looking at one possible way of achieving what you are working towards. In the next part of the series we will run through the steps you need to take in order to publish your apps once you have developed and tested them.

Android SDK: Publishing and Releasing

$
0
0

From the start of this series, we’ve been learning about creating Android applications. So far, we’ve focused on the development aspect as well as the tools you use to design, build, run, and test your applications. In this tutorial, we’ll look at the process of distributing an application through the Google Play store. Of course, you need to make sure that your applications have been tested and debugged thoroughly before you get to this stage.


Introduction

In this tutorial, we’ll focus on releasing applications through Google Play, but you can release them through other channels if you prefer. To publish an application through the Google Play store, you have to pay attention to a number of requirements, which aren’t necessarily applicable when you release your applications through another channel. However, these requirements are good practices for any publication process.


1. Preparation

Before you think about releasing an application, it goes without saying that you should have debugged and tested it thoroughly, including making sure it works on different device configurations. There are a few other things you should also do to prepare your application for release. First, if your Java code contains any log statements or other calls for outputting debug messages, you should remove these from the code prior to release.

If your manifest file has the android:debuggable attribute set, you should remove this before you export your application for release. Your manifest version attributes also need to be configured properly, but I’ll talk more about this a bit later. Make sure that your application’s resources are included in the package folders, including media items such as drawables for each configuration you have targeted. If your application uses resources such as a database, you’ll of course need to make sure these are properly prepared for use.

If your application requires any permissions, you must list these in the manifest using the uses-permission element. To publish your application, you also need to set the icon and label attributes in the manifestapplication element. Many of the items you list in the manifest will determine the details on your application’s listing in the Google Play store.


2. Versioning

We mentioned giving your application a version number and name earlier in the series. You need to include these in the android:versionCode and android:versionName attributes in the manifest, in the root manifest element.

The versionCode attribute should be an integer with each new release of your application having a higher number than the previous one. Logically you would start your version code at 1 and increment it each time you release an update, but you can in practice choose any number you like as long as each one is greater than the previous. The version code value for your application is not visible to end users. It is purely for use during the publication process and for applications to determine whether or not a version is newer than the currently installed version.

The versionName attribute, however, is a string visible by end users. This does not need to correspond to the version code, but it should increment logically, for example, starting with 1.0, followed by 1.1, and incrementing to 2.0 when your release a significant update. In other words, the version name should make sense to the end user. If you plan on releasing various versions of an application, it’s a good idea to take some time to decide in advance what version naming conventions you are going to apply.


3. Signing

Step 1

To install an application on an Android system, an application must be signed with a certificate using a private key. While you’re developing, Eclipse and the Android SDK automatically sign your application with a debug key, but you can’t publish your application if it is signed with a debug key. When you build an Android application, the system will build them either in debug or release mode. When building an application for release, you need to use your own private key to sign it.

You can generate a key for your application using the keytool utility, which is part of the Java Development Kit or JDK for short. Visit the keytool documentation for more on this. When you create a keystore for your private key, you choose an alias name and password you’ll need to have at hand when you sign your application.

Step 2

When your key/keystore are ready for signing your application, it is time to build a release version of it. In Eclipse, select your application project in the Package Explorer, right click it or choose File and select Export. Expand the Android folder, choose Export Android Application and click Next.

Export Project

Next, Eclipse will highlight any errors it encountered during the build process, which you should address before continuing. If no errors were encountered, you can click Next to continue. In the Keystore Selection window, browse to your keystore file and enter its password for it. Next, select the alias you chose for the key from the menu and enter your password. Click Next when you’re ready.

Signing Key

Select a location and choose a name for your application’s APK file. The APK file is the file you’ll upload to Google Play and that users will download onto their devices during the installation process. Eclipse takes care of signing your application with the correct key and certificate. After clicking Finish, the APK file should be in the location you selected. You should now be able to copy the APK file to an Android device. Once you have it copied on a device, select the APK file by using a file explorer application and follow the instructions to install it. If you signed the application correctly, the system should be able to install the application and you should be able to run the release version of your application on the device.

Make sure to keep your release key safe as you will only be able to release updates in the same package if they are signed using the same key. If you use a different certificate for an updated version of an application, you will also need to use a different package name.

Tip: You will need to take additional steps when publishing certain applications, for example, applications using the Google Maps library, with which you need a release key for the Maps API.


4. Publishing

Once you have a release APK file, you are ready to publish your application on Google Play. You will need a range of additional resources for publishing your application, some of which you may want to prepare in advance. These include marketing images and your application’s description, which will be included in your application listing. You will also need to set various properties for your application’s entry in the store, including pricing if your application is not free, details of in-app billing if applicable, language settings, etc.

To begin the publication process, log in to your Google account and navigate to the Developer Console. Click Add New Application and, in the pop-up that appears, select your application’s default language and enter your application’s name. From here on, you can prepare the listing for the application and upload your newly created APK file.

As you’ll notice, the Google Play listing for your application requires a lot of detail and the publication process can take some time. In the main listings section for each application, you can include graphic assets, such as icons and screenshots, videos, application description, categories, content ratings, and your contact details. To see how these will be listed in Google Play, look at other listings on the Google Play store.

In the Pricing and Distribution section of your application’s listing, you need to specify whether you’re going to charge for the product or not by setting a price. Keep in mind that free applications cannot be changed into paid applications. However, you can modify the price of a paid application or make a paid application free. It is also possible to use in-app billing in a free application. If your application is available in various countries, Google Play can automatically convert the price to other currencies. Feel free to further explore other sections of the listing, such as in-app products and APIs.

If you have published one or more applications on Google Play, you can view some statistics in the Developer Console. The console provides developers with detailed reports. You can configure the statistics section of a listing to give you an overview of its performance in terms of Android version, application version, country, device, and language. Other statistics include installs and revenue reports, detailed crash reports, ratings, and reviews. In contrast to Apple’s App Store, developers can reply to reviews and start a dialog with your application’s users. Once you have an application listed in Google Play, you can link to the application listing page for promotional purposes.

Before going through the publication process for an application, read through the Launch Checklist.


Conclusion

If you are just getting started on Android, you may be a long way from publishing your first application, but understanding the publication process is still worthwhile at this stage. Publishing an application for the first time may be time-consuming, but uploading upgrades is much faster once you have the initial details and assets filled in. In the next part of this series, we will outline some directions you can consider to continue learning Android development. After that, we’ll finish the series up with a quiz testing you on what you’ve learned so far.

Viewing all 1836 articles
Browse latest View live