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

Create a Balloon Racing Game in Unity Using the Microphone

$
0
0
tag:code.tutsplus.com,2005:PostPresenter/cms-21667
Final product image
What You'll Be Creating

Introduction

In this tutorial, you'll learn how to create a 2D game using C# and Unity. We'll be taking advantage of Unity's microphone support to enhance the gameplay of the game. The objective of the game is simple, reaching the other side of the level by avoiding the obstacles along the way. The player can move the main character by blowing on the device's microphone, moving it upwards.

You'll learn the following aspects of Unity game development in this tutorial:

  • setting up a 2D project in Unity
  • importing sprites
  • microphone controls
  • working with physics collisions

1. Create a New Unity Project

Open Unity and select New Project from the File menu to open the new project dialog. Tell Unity where you want to save the project and set the Set up defaults for: menu to 2D.

 

2. Build Settings

In the next step, you're presented with Unity's user interface. Set the project up for your preferred platform by choosing Build Settings from the File menu and selecting the target platform.

3. Unity User Interface

Before we get started, make sure the 2D button in the Scene panel is highlighted. You can also modify the current resolution in the Game panel.

You should also see Unity's workspace panels, which we'll use in this tutorial. Take a moment to explore Unity's user interface, such as the Scene, Game, Hierarchy, Project, Assets, and Inspector. We'll be using them a lot in this tutorial.

4. Game Interface

Our game's user interface is going to be straightforward. The next screenshot gives you an idea of the assets we'll be using and how the game's final user interface will end up looking. You can find the assets we'll be using in the source files on GitHub.


5. Programming Language

You can use one of three programming languages when using Unity, C#, UnityScript, a variation of JavaScript, and Boo. Each of these programming languages has its pros and cons and it's up to you to decide which one you prefer. My personal preference goes to the C# programming language and that's the language I'll be using in this tutorial.

If you decide to use another programming language, then make sure to take a look at Unity's Script Reference for examples.

6. Assets & Sound Effects

Before we start coding, we need to add the assets to the Unity project. You can do this one of several ways:

  • select Import New Asset from the Assets menu
  • add the items to the assets folder in your project
  • drag and drop the assets in the project window

After completing this step, you should see the assets in your project's Assets folder in the Project panel.

We'll use a number of sounds to create a great audial experience. The sound effects used in this tutorial were obtained from freesound.org.

7. Background

Start by dragging and dropping the background into the Hierarchy panel. It should automatically appear in the Scene panel.


8. Camera Size

Because the Scene panel is set to display a 2D view, you'll notice that selecting the Main Camera in the Hierarchy shows a preview of what the camera is going to display. You can also see this in the Game view. To make the entire scene visible, set the Size value of the Main Camera to 4 in the Inspector panel as shown below.

9. Sprite Sheet

We'll use a sprite sheet for our game's user interface elements. Unity has a sprite editor that makes using sprites a breeze. The artwork used in this tutorial was obtained from openclipart.org.

Import the artwork, select it from the Assets panel, and change the Sprite Mode option to Multiple in the Inspector panel.

Click the button labeled Sprite Editor and set the Type option to Automatic.

10. Cow Rigidbody 2D

With the sprite sheet sliced and ready to use, click the arrow that appears when the sprite sheet is selected and choose the sprite of the cow, the main character of our game. Drag it to the scene to add it.

To detect collisions, at least one of the colliding objects needs to have a Rigidbody 2D component attached to it. To add one to the cow, click the Add Component button in the Inspector panel. From the list of components, select RigidBody 2D in the Physics 2D section.

Check the Fixed Angle box to prevent the cow from rotating if a collision occurs. We won't be using the default physics gravity in this game, instead we'll simulate our own. Change the Gravity Scale from 1 to 0 to ensure the default gravity doesn't impact the object.

11. Adding Colliders

The floor is used to keep our main character from falling once we've added physics to the game. Create a new game object by selecting Create Empty from the GameObject menu.

To make the floor detect when the character is touching it, we need to add a Box Collider 2D component. A collider is a physics shape that defines the area that triggers a collision.

Select the floor game object in the Hierarchy, open the Inspector panel, and click Add Component. From the list of components, select Box Collider 2D in the Physics 2D section.

Change the Size property to X: 4.8 and Y: 0.05 to create a small rectangle where the cow will be positioned. Finally, add a Box Collider 2D to the cow game object by repeating these steps.

12. Cow Audio Source

An Audio Source component is used to play an audio clip when the player collects the star. This component will read the audio clip set in its options and play it when called from a script or at the start if the Play on Awake checkbox is selected.

To play a sound when the player collects a star, we first need to attach an Audio Source component to it. Select the star from the Hierarchy or Scene view, click the Add Component button in the Inspector panel, and select Audio Source in the Audio section.

As we only want the sound to play when the player touches the star, we need to uncheck the Play on Awake option. Click the little dot on the right, below the gear icon, to select the sound we want to play.

13. Adding Balloons

The balloons represent the lives or health of our main character. When a hand collides with the cow, it will pop one of the balloons to indicate that it was hit and the number of lives has decreased.

Drag the balloon sprite from the Assets to the Hierarchy panel and then back to the Assets. This will create a prefab of the balloon. You'll notice the text becomes blue indicating it's now a prefab. By creating a prefab, we can reuse the balloon without using additional resources.

Select the new prefab and press Command+D to duplicate it. Use the Rotation tool to slightly rotate the balloons as shown in the above screenshot.

We group the cow and balloons to make moving them a bit easier. To do this, drag a balloon from the Hierarchy panel and place it on top of the cow game object in the Hierarchy panel. The cow game object is highlighted to indicate that dropping the balloon onto it will add it as a child of the cow game object. The result is that moving the cow game object also moves the position of the balloons.

14. Adding Obstacles

The hands are the enemies or obstacles that need to be avoided if the player wants to finish the level by collecting the star. The hands move from side to side, leaving a narrow gap in the middle for the cow to pass through.

Because the hands are game objects that we'll use multiple times, we first convert it to a prefab as we did with the balloons. Follow the above steps to create the prefab and use the editor tools to position the hands as shown in the above screenshot.

We also need to add a collider to each hand to detect collisions. To add the collider, click the Add Component button in the Inspector panel and select Box Collider 2D in the Physics 2D section. You'll notice that a green box appears around the hand when you select it to indicate the hand has a collider tied to it.

We also play a sound when a hand collides with the cow, popping a balloon. To accomplish this, we first need to add the sound. Select the hand from the Hierarchy or Scene view, click the Add Component button in the Inspector panel, and select Audio Source from the Audio section.

The details of the audio component will show up in the Inspector Panel. Click the dot below the gear icon to select the correct sound.

15. Adding the Star

The goal of the game is to collect the star at the end of each level. The player can move the cow upwards by blowing on the device's microphone.

Drag the star from the Assets panel and add it to the Scene. In the Inspector's Transform section, change the values as shown in the screenshot below to position the star.

This will place the star at the top of the level. To detect when the cow collects the star, we need to add a collider to it like we've done a few times already. Add a Box Collider 2D to the star.

16. Adding Alerts

Alerts are also game objects. They are messages informing the player when the level has been completed or the game is over.

Drag the alerts from the Assets panel to the Hierarchy and then back to the Assets panel to convert them to a prefab. Later in this tutorial, we'll add a script to the alerts and show how they are used. Don't forget to delete them from the Scene once you've converted them to a prefab.

17. Adding Scripts

Unity includes a code editor, a version of Mono Develop. While it's a good editor, you can use whatever editor you like. Visual Studio, for example, is a popular choice if you're using Windows.

You can create a new file by launching your code editor, saving the file in the Assets folder of your project, and then adding it to a GameObject, just like you do with a component. Alternatively, you can create a new script in the Inspector by selecting New Script and then double-clicking it to open it.

18. Detecting Microphone Input

To move our main character, we'll need access to the device's microphone. By default, Unity provides basic support for capturing audio, but it doesn't include a property or method to detect the microphone's activity level, which is what we need to move the cow.

Fortunately, we can use a third party script that will give us access to a loudness property. The loudness property will allow us, along with transform.position, to move the cow.

Create an empty GameObject and name it MicrophoneInput. Use the Add Component button to attach the aforementioned script and an Audio Source component to the new game object.

By doing this, we enable the script and the application will start capturing the microphone's input. By adjusting the Sensitivity property in the Inspector, we control how much the cow is moved by the input of the microphone. The higher the value, the faster the cow will move. I've found that 50 is a good value to start with.

19. Moving the Hands

The following script defines the Hand class and controls the movement of the hands. The hands continuously move from left to right and vice versa. Let's see how this works.

Step 1: Properties

The first property we use in the script is moveSpeed, a float that defines the number of units a hand moves during every frame. It sets the x value of the transform.position property, moving the hand horizontally.

The second property, currentPos, is also a float and stores the current position of the hand before it moves. This will help us calculate the number of units the hand can move.

using UnityEngine;
using System.Collections;

public class Hand : MonoBehaviour
{
    private float moveSpeed = 0.02f;
    private float currentPos;
    public bool left = false;

Lastly, the left property of type boolean defines if the hand is moving to the left. This makes it easy to change the direction of a hand by setting the left variable to either true or false.

Step 2: Start Method

The Start method is a method defined in the MonoBehaviour class that is called during initialization, before any other method is called—with the exception of Awake, which we won't cover in this tutorial.

In the Start method, we can configure the object before any other code is run. In this case, we set the currentPos property to the hand's current position, before it has moved.

void Start()
{
    currentPos = transform.position.x;
}

Step 3: Change Position

In the Update method, we check if the hand is left or right, and move it in the correct direction during every frame. To do this, we write an if statement inside the Update method and decrease or increase the x position using the moveSpeed variable to modify the position property.

void Update()
{
    /* Move Hand */

    /* Move to the right if hand is on the left side */

    if (!left)
    {
        transform.position -= new Vector3(moveSpeed, 0, 0);
    } else
    {
        transform.position += new Vector3(moveSpeed, 0, 0);
    }

    /* Change moveSpeed to move in the other direction, creating a movement loop */

    if (transform.position.x <= currentPos - 0.7f)
    {
            moveSpeed *= -1;
    }
    if (transform.position.x >= currentPos + 0.7f)
    {
        moveSpeed *= -1;
    }
}
}

When the hand moves 0.7 units, we multiply the moveSpeed property by -1 to make the hand move in the opposite direction. The result is that the hands move from one side to the other in a continuous loop, making it harder for the cow to pass through the hands and reaching the star.

20. Cow Script

Create a new script and attach it to the cow game object. This script will handle the player's actions and a few other functions related to the game's mechanics, such as displaying the alerts. Let's take a look at the properties used in this script.

using UnityEngine;
using System.Collections;

public class Cow : MonoBehaviour
{
    private Vector3 gravity = new Vector3(0, 0.02f, 0);
    public GameObject micVolume;
    private float moveSpeed;
    private byte balloons = 3;
    public GameObject alertWin;
    public GameObject alertLose;
}
  • gravity: used to simulate a vertical force, it pulls the cow downwards
  • micVolume: reference to the MicrophoneInput game object
  • moveSpeed: gets the loudness value from the MicrophoneInput class
  • balloons: holds number of balloons, this value represents the player's lives
  • alertWin: reference to the alertWin game object
  • alertLose: reference to the alertLose game object

Note that public variables need to be set up in the Unity's editor. They are all references to prefabs. Setting the value of a variable in the editor is easy. Save the script and make sure there are no errors. Then switch back to Unity and select the game object to which the script is attached. You should see the variables listed below the script component as shown below.

Drag and drop the required or preferred asset to the variable, or click the little dot below the gear icon to select it.

Make sure that the asset and the variable are of the same type or you won't be able to drop it or see it when you click on the dot icon.

21. Moving the Cow

Step 1: Moving

To move the cow upwards, we'll use the FixedUpdate method. Why not the regular Update method? This method is a predefined MonoBehaviour method that runs every fixed frame rate instead of every frame. This means that it will be smooth even if the current frame rate is a little low. Add the following code block to the script:

void FixedUpdate()
{
    /* Move Cow upwards based on Mic volume */

    moveSpeed = micVolume.GetComponent<MicrophoneInput>().loudness * 0.01f;
    transform.position = new Vector3(0, transform.position.y + moveSpeed, 0);
    /* Simulate our own gravity (this one doesn't get stronger when high) */

    transform.position -= gravity;
}

We calculate the speed by getting the current loudness of the microphone. This loudness is obtained from the MicrophoneInput class and then multiplied by 0.01. We do this to prevent the cow from moving too fast.

The cow character is moved by increasing the y value of the transform.position property, using the speed we stored in stored in moveSpeed.

Step 2: Simulating Gravity

In addition to moving the cow, we also apply a downward force to it, the gravity. We achieve this by decreasing the position of the cow using the gravity vector we created earlier. Doing this will constantly reduce the y position of the cow without making it fall faster, which happens if we were to use the default gravity behavior.

22. Hands Collision

Step 1: Detecting Collisions

In the next step, we detect if any of the hands collide with the cow. The OnTriggerEnter2D method runs when two objects collide without physics interaction. In this case, we check if the cow collides with an object named "Hand", which can be any of the hands on the scene, and play the audio attached to the cow game object if the collision occurs. You'll notice we also inspect the cow's alpha property. Why we do this is explained in the next step.

void OnTriggerEnter2D(Collider2D other)
{
    /* Hands Collision */

    if (other.name == "Hand" && transform.GetComponent<SpriteRenderer>().color.a == 1)
    {
        other.audio.Play();

Step 2: Preventing Multiple Collisions

Collisions are tested multiple times every frame, meaning that three collisions will occur in a very short time popping all the balloons. Since we don't want this to happen, we need a way to prevent this.

A useful way to do this is to change the alpha of the hit object. This will also give the user visual feedback indicating that it has been hit. The next lines will take care of that.

/* Prevent from multiple collision */

Color alpha = new Color(1, 1, 1, 0.5f);
transform.GetComponent<SpriteRenderer>().color = alpha;
Invoke("EnableCollision", 1);

We first create a new Color object and assign it the color of the game object and set the alpha value to 0.5 to make it semi-transparent. We then access the game object SpriteRenderer, which lets us modify its color.

The last line in this block of code waits a second and then calls a the EnableCollision function. This  function resets the color values of the cow making it able to detect a collision again. We'll implement this function later in this tutorial.

23. Removing Balloons

When the cow is hit by a hand, one balloon needs to be removed. We call the Destroy method on a balloon game object. We use the Find function, because we don't have a reference to each of the balloons.

This function searches the game's assets and returns the game object that we're looking for, in this case a balloon.

/* Remove Balloon */

Destroy(GameObject.Find("Balloon"));
balloons--;

But wait, aren't there three balloons in the scene? That is correct. However, the Find function returns the first match it can find. In other words, it returns the first balloon game object it finds.

We also decrement the balloons counter to help us know when the cow has lost all its lives.

24. Game Over

The game is over when all the balloons have been popped. To test this, we check if balloons is equal to 0 and display an alert if true. We also set the gravity's y property to 0 and pause the game by setting timeScale to 0.

The timeScale property controls how time passes in the game environment. It can be used to make the game faster or slower based on its value. The default time scale is 1.0, increasing its value accelerates the frame rate associated functions and decreasing it slows them down. Setting it to 0 pauses the game, preventing any new collisions.

/* Game Over */

    if(balloons == 0)
    {
        GameObject alert = Instantiate(alertLose, new Vector3(0, 0, 0), transform.rotation) as GameObject;
        gravity.y = 0;
        Time.timeScale = 0;
    }
}

25. Level Complete

When the player gets to the other side of the level we need to remove the star and display an alert indicating that the level has been completed.

The if statement checks if the collision is in fact with the star game object and plays the audio attached to the cow if the name is correct. We then remove the star from the scene before creating the alert. We also set the gravity's y property to 0 as we did in the previous step.

/* Star Collision */

    if (other.name == "Star")
    {
        audio.Play();
        Destroy(other.gameObject);
        GameObject alert = Instantiate(alertWin, new Vector3(0, 0, 0), transform.rotation) as GameObject;
        gravity.y = 0;
    }
}

26. Enabling Collisions

The EnableCollision method resets the alpha value of the cow game object after it has been hit by a hand. Doing this will enable the cow game object to detect another hit. Note that the Color object has an alpha of 1.

void EnableCollision()
{
    Color alpha = new Color(1, 1, 1, 1);
    transform.GetComponent<SpriteRenderer>().color = alpha;
}

27. Restarting the Game

The Reload method uses the Application class to reload the current level. Create a new script named Restart , add the following code block to it, and attach it to both of the alert prefabs we created earlier.

using UnityEngine;
using System.Collections;

public class Restart : MonoBehaviour
{
    void Update()
    {
        if (Input.GetButton("Fire1"))
        {
            Reload();
        }
    }

    void Reload()
    {
        Application.LoadLevel(Application.loadedLevel);
    }
}

We first test if the user taps on the screen using the Input class and call the Reload method if true. The implementation of the Reload method is short and simple. All we do is load the current level, reseting every object and variable to its initial state.

28. Testing

It's time to test the game. Press Command-P to play the game in Unity. If everything works as expected, you are ready for the final steps.

29. Player Settings

When you're happy with your game, it's time to select Build Settings from the File menu and click the Player Settings button. This should bring up the Player Settings in the Inspector panel where you can set the parameters for your application.

These settings are application-specific and include the creator or company, application resolution, display mode, etc. These settings depend on the devices you're targeting and the stores or markets you will be publishing your game on.

30. Build and Play

Once your project is properly configured, it's time to revisit the Build Settings and click the Build button. That's all it takes to build your game for testing and/or distribution.

Conclusion

In this tutorial, we've learned how to implement microphone controls, physics interaction, sprite sheets, and other aspects of game development using Unity. I encourage you to experiment with the result and customize the game to make it your own. I hope you liked this tutorial and found it helpful.

2014-08-29T15:20:50.000Z2014-08-29T15:20:50.000ZCarlos Yanez

Create a Weather App on Android

$
0
0
tag:code.tutsplus.com,2005:PostPresenter/cms-21587
Final product image
What You'll Be Creating

A lot of the popular weather apps on Google Play are either full of ads, require too many permissions, or include features that most of us never use. Wouldn't it be great if you could build your own weather app from scratch?

In this tutorial, I'm going to show you how. Our app will have a simple and minimalist user interface, showing the user exactly what they need to know about the current weather conditions. Let's get started.

1. Prerequisites

Before you continue, double-check that you have the following set up:

  • Eclipse ADT Bundle: You can download it at the Android Developer website.
  • OpenWeatherMap API Key : This isn't required to complete the tutorial, but it's free. You can obtain one by signing up at the OpenWeatherMap website.
  • Icons: I recommend you download the weather icons font created by Erik Flowers. You need to download the TTF file, because we'll be using it in a native app. We'll use the font to render various icons depending on the weather conditions.

2. Create a New Project

I'm going to call this app SimpleWeather, but feel free to give it any name you like. Enter a unique package name, set the minimum required SDK to Android 2.2, and set the target SDK to Android 4.4. You can leave the theme at Holo Dark.

Create a new Android Application

This app will only have one Activity and it will be based on the Blank Activity template as shown below.

Create a new activity

Name the Activity WeatherActivity. We'll be using a Fragment inside this Activity. The layout associated with the Activity is activity_weather.xml. The layout associated with the Fragment is fragment_weather.xml.

The Activity details screen

3. Add the Custom Font

Copy weathericons-regular-webfont.ttf to your project's assets/fonts directory and rename it to weather.ttf.

4. Edit the Manifest

The only permission this app needs is android.permission.INTERNET.

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

To keep this tutorial simple, we're only going to support portrait mode. The activity node of the manifest should look like this:

<activity
    android:name="ah.hathi.simpleweather.WeatherActivity"
    android:label="@string/app_name"
    android:screenOrientation="portrait"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity>

5. Edit the Activity's Layout

There isn't much to change in activity_weather.xml. It should already have a FrameLayout. Add an extra property to change the color of the background to #FF0099CC.

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="ah.hathi.simpleweather.WeatherActivity"
    tools:ignore="MergeRootFrame"
    android:background="#FF0099CC" />

6. Edit the Fragment's Layout

Edit fragment_weather.xml by adding five TextView tags to show the following information:

  • city and country
  • current temperature
  • an icon showing the current weather condition
  • a timestamp telling the user when the weather information was last updated
  • more detailed information about the current weather, such as description and humidity

Use a RelativeLayout to arrange the text views. You can adjust the textSize to suit various devices.

<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="ah.hathi.simpleweather.WeatherActivity$PlaceholderFragment" ><TextView
        android:id="@+id/city_field"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:textAppearance="?android:attr/textAppearanceLarge" /><TextView
        android:id="@+id/updated_field"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/city_field"
        android:layout_centerHorizontal="true"
        android:textAppearance="?android:attr/textAppearanceMedium"
        android:textSize="13sp" /><TextView
        android:id="@+id/weather_icon"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"        
        android:layout_centerVertical="true"
        android:layout_centerHorizontal="true"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:textSize="70sp"
        /><TextView
        android:id="@+id/current_temperature_field"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:textSize="40sp" /><TextView 
        android:id="@+id/details_field"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/weather_icon"
        android:layout_centerHorizontal="true"
        android:textAppearance="?android:attr/textAppearanceMedium"
        />        </RelativeLayout>

7. Edit strings.xml

This file contains the strings used in our app as well as the Unicode character codes that we'll use to render the weather icons. The application will be able to display eight different types of weather conditions. If you want to handle more, then refer to this cheat sheet. Add the following to values/strings.xml:

<?xml version="1.0" encoding="utf-8"?><resources><string name="app_name">Simple Weather</string><string name="change_city">Change city</string><!-- Put your own APP ID here --><string name="open_weather_maps_app_id">11111</string><string name="weather_sunny">&#xf00d;</string><string name="weather_clear_night">&#xf02e;</string><string name="weather_foggy">&#xf014;</string><string name="weather_cloudy">&#xf013;</string><string name="weather_rainy">&#xf019;</string><string name="weather_snowy">&#xf01b;</string><string name="weather_thunder">&#xf01e;</string><string name="weather_drizzle">&#xf01c;</string><string name="place_not_found">Sorry, no weather data found.</string>    </resources>

8. Add a Menu Item

The user should be able to choose the city whose weather they want to see. Edit menu/weather.xml and add an item for this option.

<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    tools:context="ah.hathi.simpleweather.WeatherActivity" ><item
        android:id="@+id/change_city"
        android:orderInCategory="1"
        android:title="@string/change_city"
        app:showAsAction="never"/></menu>

Now that all the XML files are ready to use, let's move on and query the OpenWeatherMap API to fetch weather data.

9. Fetch Data From OpenWeatherMap

We can get the current weather details of any city formatted as JSON using the OpenWeatherMap API. In the query string, we pass the city's name and the metric system the results should be in.

For example, to get the current weather information for Canberra, using the metric system, we send a request to http://api.openweathermap.org/data/2.5/weather?q=Canberra&units=metric

The response we get back from the API looks like this:

{
    "base": "cmc stations", 
    "clouds": {
        "all": 90
    }, 
    "cod": 200, 
    "coord": {
        "lat": -35.28, 
        "lon": 149.13
    }, 
    "dt": 1404390600, 
    "id": 2172517, 
    "main": {
        "humidity": 100, 
        "pressure": 1023, 
        "temp": -1, 
        "temp_max": -1, 
        "temp_min": -1
    }, 
    "name": "Canberra", 
    "sys": {
        "country": "AU", 
        "message": 0.313, 
        "sunrise": 1404335563, 
        "sunset": 1404370965
    }, 
    "weather": [
        {
            "description": "overcast clouds", 
            "icon": "04n", 
            "id": 804, 
            "main": "Clouds"
        }
    ], 
    "wind": {
        "deg": 305.004, 
        "speed": 1.07
    }
}

Create a new Java class and name it RemoteFetch.java. This class is responsible for fetching the weather data from the OpenWeatherMap API.

We use the HttpURLConnection class to make the remote request. The OpenWeatherMap API expects the API key in an HTTP header named x-api-key. This is specified in our request using the setRequestProperty method.

We use a BufferedReader to read the API's response into a StringBuffer. When we have the complete response, we convert it to a JSONObject object.

As you can see in the above response, the JSON data contains a field named cod. Its value is 200 if the request was successful. We use this value to check whether the JSON response has the current weather information or not.

The RemoteFetch.java class should look like this:

package ah.hathi.simpleweather;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;

import org.json.JSONObject;

import android.content.Context;
import android.util.Log;

public class RemoteFetch {

    private static final String OPEN_WEATHER_MAP_API = 
			"http://api.openweathermap.org/data/2.5/weather?q=%s&units=metric";
	public static JSONObject getJSON(Context context, String city){
		try {
			URL url = new URL(String.format(OPEN_WEATHER_MAP_API, city));			
			HttpURLConnection connection = 
					(HttpURLConnection)url.openConnection();
			connection.addRequestProperty("x-api-key", 
					context.getString(R.string.open_weather_maps_app_id));
			BufferedReader reader = new BufferedReader(
					new InputStreamReader(connection.getInputStream()));
			StringBuffer json = new StringBuffer(1024);
			String tmp="";
			while((tmp=reader.readLine())!=null)
				json.append(tmp).append("\n");
			reader.close();
			JSONObject data = new JSONObject(json.toString());
			// This value will be 404 if the request was not
			// successful
			if(data.getInt("cod") != 200){
				return null;
			}
			return data;
		}catch(Exception e){
			return null;
		}
	}	
}

10. Store the City as a Preference

The user shouldn't have to specify the name of the city every time they want to use the app. The app should remember the last city the user was interested in. We do this by making use of SharedPreferences. However, instead of directly accessing these preferences from our Activity class, it is better to create a separate class for this purpose.

Create a new Java class and name it CityPreference.java. To store and retrieve the name of the city, create two methods setCity and getCity. The SharedPreferences object is initialized in the constructor. The CityPreference.java class should look like this:

package ah.hathi.simpleweather;

import android.app.Activity;
import android.content.SharedPreferences;

public class CityPreference {
    
	SharedPreferences prefs;
	
	public CityPreference(Activity activity){
		prefs = activity.getPreferences(Activity.MODE_PRIVATE);
	}
	
    // If the user has not chosen a city yet, return
    // Sydney as the default city
	String getCity(){
		return prefs.getString("city", "Sydney, AU");        
	}
	
	void setCity(String city){
		prefs.edit().putString("city", city).commit();
	}
	
}

11. Create the Fragment

Create a new Java class and name it WeatherFragment.java. This fragment uses fragment_weather.xml as its layout. Declare the five TextView objects and initialize them in the onCreateView method. Declare a new Typeface object named weatherFont. The TypeFace object will point to the web font you downloaded and stored in the assets/fonts folder.

We will be making use of a separate Thread to asynchronously fetch data from the OpenWeatherMap API. We cannot update the user interface from such a background thread. We therefore need a Handler object, which we initialize in the constructor of the WeatherFragment class.

public class WeatherFragment extends Fragment {
    Typeface weatherFont;
	TextView cityField;
	TextView updatedField;
	TextView detailsField;
	TextView currentTemperatureField;
	TextView weatherIcon;
	Handler handler;

	public WeatherFragment(){	
		handler = new Handler();
	}

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment_weather, container, false);
        cityField = (TextView)rootView.findViewById(R.id.city_field);
        updatedField = (TextView)rootView.findViewById(R.id.updated_field);
        detailsField = (TextView)rootView.findViewById(R.id.details_field);
        currentTemperatureField = (TextView)rootView.findViewById(R.id.current_temperature_field);
        weatherIcon = (TextView)rootView.findViewById(R.id.weather_icon);
        
        weatherIcon.setTypeface(weatherFont);
        return rootView; 
    }
}

Initialize the weatherFont object by calling createFromAsset on the Typeface class. We also invoke the updateWeatherData method in onCreate.

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);  
	weatherFont = Typeface.createFromAsset(getActivity().getAssets(), "fonts/weather.ttf");    	
	updateWeatherData(new CityPreference(getActivity()).getCity());
}

In updateWeatherData, we start a new thread and call getJSON on the RemoteFetch class. If the value returned by getJSON is null, we display an error message to the user. If it isn't, we invoke the renderWeather method.

Only the main Thread is allowed to update the user interface of an Android app. Calling Toast or renderWeather directly from the background thread would lead to a runtime error. That is why we call these methods using the handler's post method.

private void updateWeatherData(final String city){
    new Thread(){
		public void run(){
			final JSONObject json = RemoteFetch.getJSON(getActivity(), city);
			if(json == null){
				handler.post(new Runnable(){
					public void run(){
						Toast.makeText(getActivity(), 
								getActivity().getString(R.string.place_not_found), 
								Toast.LENGTH_LONG).show(); 
					}
				});
			} else {
				handler.post(new Runnable(){
					public void run(){
						renderWeather(json);
					}
				});
			}    			
		}
	}.start();
}

The renderWeather method uses the JSON data to update the TextView objects. The weather node of the JSON response is an array of data. In this tutorial, we will only be using the first element of the array of weather data.

private void renderWeather(JSONObject json){
    try {
    	cityField.setText(json.getString("name").toUpperCase(Locale.US) + 
    			", " + 
    			json.getJSONObject("sys").getString("country"));
    	JSONObject details = json.getJSONArray("weather").getJSONObject(0);
    	JSONObject main = json.getJSONObject("main");
    	detailsField.setText(
    			details.getString("description").toUpperCase(Locale.US) +
    			"\n" + "Humidity: " + main.getString("humidity") + "%" +
    			"\n" + "Pressure: " + main.getString("pressure") + " hPa");
    	currentTemperatureField.setText(
    				String.format("%.2f", main.getDouble("temp"))+ " ℃");

    	DateFormat df = DateFormat.getDateTimeInstance();
    	String updatedOn = df.format(new Date(json.getLong("dt")*1000));
    	updatedField.setText("Last update: " + updatedOn);

    	setWeatherIcon(details.getInt("id"),
    			json.getJSONObject("sys").getLong("sunrise") * 1000,
    			json.getJSONObject("sys").getLong("sunset") * 1000);
    	
	}catch(Exception e){
		Log.e("SimpleWeather", "One or more fields not found in the JSON data");
	}
}

At the end of the renderWeather method,  we invoke setWeatherIcon with the id of the current weather as well as the times of sunrise and sunset. Setting the weather icon is a bit tricky, because the OpenWeatherMap API supports more weather conditions than we can support with the web font we're using. Fortunately, the weather ids follow a pattern, which you can read more about on the OpenWeatherMap website.

This is how we map a weather id to an icon:

  • the weather codes in the 200 range are related to thunderstorms, which means we can use R.string.weather_thunder for these
  • the weather codes in the 300 range are related to drizzles and we use R.string.weather_drizzle for these
  • the weather codes in the 500 range signify rain and we use R.string.weather_rain for them
  • and so on ...

We use the sunrise and sunset times to display the sun or the moon, depending on the current time of the day and only if the weather is clear.

private void setWeatherIcon(int actualId, long sunrise, long sunset){
    int id = actualId / 100;
	String icon = "";
	if(actualId == 800){
		long currentTime = new Date().getTime();
		if(currentTime>=sunrise && currentTime<sunset) {
			icon = getActivity().getString(R.string.weather_sunny);
		} else {
			icon = getActivity().getString(R.string.weather_clear_night);
		}
	} else {
    	switch(id) {
    	case 2 : icon = getActivity().getString(R.string.weather_thunder);
		 		 break;     	
    	case 3 : icon = getActivity().getString(R.string.weather_drizzle);
		 		 break;    	
    	case 7 : icon = getActivity().getString(R.string.weather_foggy);
    			 break;
    	case 8 : icon = getActivity().getString(R.string.weather_cloudy);
		 		 break;
    	case 6 : icon = getActivity().getString(R.string.weather_snowy);
		 		 break;
    	case 5 : icon = getActivity().getString(R.string.weather_rainy);
    			 break;
    	}
	}
	weatherIcon.setText(icon);
}

Of course, you can handle more weather conditions by adding more case statements to the switch statement of the setWeatherIcon method.

Finally, add a changeCity method to the fragment to let the user update the current city. The changeCity method will only be called from the main Activity class.

public void changeCity(String city){
    updateWeatherData(city);
}

12. Edit the Activity

During the project's setup, Eclipse populated WeatherActivity.java with some boilerplate code. Replace the default implementation of the onCreate method with the one below in which we use the WeatherFragment. The onCreate method should look like this:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_weather);

    if (savedInstanceState == null) {
        getSupportFragmentManager().beginTransaction()
                .add(R.id.container, new WeatherFragment())
                .commit();
    }
}

Next, edit the onOptionsItemSelected method and handle the only menu option we have. All you have to do here is invoke the showInputDialog method.

In the showInputDialog method, we use AlertDialog.Builder to create a Dialog object that prompts the user to enter the name of a city. This information is passed on to the changeCity method, which stores the name of the city using the CityPreference class and calls the Fragment's changeCity method.

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    if(item.getItemId() == R.id.change_city){
		showInputDialog();
	}
	return false;
}

private void showInputDialog(){
	AlertDialog.Builder builder = new AlertDialog.Builder(this);
	builder.setTitle("Change city");
	final EditText input = new EditText(this);
	input.setInputType(InputType.TYPE_CLASS_TEXT);
	builder.setView(input);
	builder.setPositiveButton("Go", new DialogInterface.OnClickListener() {
		@Override
		public void onClick(DialogInterface dialog, int which) {
			changeCity(input.getText().toString());
		}
	});
	builder.show();
}

public void changeCity(String city){
	WeatherFragment wf = (WeatherFragment)getSupportFragmentManager()
							.findFragmentById(R.id.container);
	wf.changeCity(city);
	new CityPreference(this).setCity(city);
}

Your weather app is now ready. Build the project and deploy it to an Android device for testing.

The app running on a tablet

Conclusion

You now have a fully functional weather application. Feel free to explore the OpenWeatherMap API to further enhance your application. You may also want to make use of more weather icons, because we are currently using only a small subset of them.

2014-09-01T16:45:48.000Z2014-09-01T16:45:48.000ZAshraff Hathibelagal

Windows Phone 8: An Introduction to XAML

$
0
0
tag:code.tutsplus.com,2005:PostPresenter/cms-20476

Developing software is usually a two step process that involves developing the user interface and the business logic of the application. Windows Phone is no exception to this paradigm. When developing for Windows Phone, XAML is used for the implementation of the user interface of Windows Phone applications.

1. What is XAML?

XAML or Extensible Application Markup Language is a declarative language developed by Microsoft and used in Windows Phone to create graphical user interface objects. If you're familiar with XML, then a code snippet of XAML will look very familiar. XAML is to a C# developer what HTML is to a web developer. It is the basis of user interface design for Windows Phone.

The Windows Phone platform has a lot of building blocks at its disposal, such as Buttons, Text Blocks, Text Boxes, etc. Even though it's possible to develop a Windows Phone 8 application using only C#, it is impractical and cumbersome.

XAML makes creating user interfaces much easier. After creating a new Windows Phone 8 project or page in Visual Studio, you are presented with two views. One view displays the XAML code while the other view shows the developer its visual design representation.

To better understand this, let's revisit the project we created in the previous tutorial in which we created our first Windows Phone 8 application.

<Grid x:Name="LayoutRoot" Background="Transparent"><Grid.RowDefinitions><RowDefinition Height="Auto"/><RowDefinition Height="*"/></Grid.RowDefinitions><!--TitlePanel contains the name of the application and page title--><StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28"><TextBlock Text="MY APPLICATION" Style="{StaticResource PhoneTextNormalStyle}" Margin="12,0"/><TextBlock Text="page name" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/></StackPanel><!--ContentPanel - place additional content here--><Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"></Grid></Grid>

You immediately notice the same hierarchical structure you find in XML and HTML. Each element in the XAML code represents a Windows Phone control, which we will be discussing later on in this series. You'll notice that each element has an opening and closing tag, just like in XML or HTML. You can also see that some elements have additional attributes, taking the following structure:

<ElementName Property1="Value" Property2="Value" ...><ChildElementName Property="Value"></ChildElementName></ElementName>

I will refer to each element in the XAML file as a control as they represent Windows Phone controls, which are objects that are a part of the framework. Each of these controls can have properties attached to them. Some of these controls, such as the Grid and StackPanel controls, can even contain other controls within them. For example, look how the StackPanel control with the Name property of TitlePanel contains two TextBlock controls.

This hierarchical arrangement of elements enables developers to design the user interface of Windows Phone applications with much more ease and also provides structure between controls that make up the user interface of a Windows Phone application.

2. XAML versus Code

As I said earlier in this article, it is possible to create the entire user interface of a Windows Phone application in C#, without using XAML. In reality, however, this is not very practical. This isn't recommended, because it makes designing the application's user interface untidy and a bit all over the place.

In addition, strictly using C# to create the application's user interface will significantly limit the possibility of using the MVVM design pattern that is baked into Windows Phone development. This means advanced techniques, such as data binding, will be more difficult to implement.

Let's take a close look at the two techniques, XAML and C#, to building an application's user interface. For this comparison, I'll first show how a TextBlock and a Button control are declared within a StackPanel control using XAML. I will then show you the equivalent in C#.

XAML

<StackPanel><TextBlock Margin="20">A Simple TextBlock</TextBlock><Button Margin="10" HorizontalAlignment="Right" Content="Simple Button"></Button></StackPanel>

You can see how declarative the above XAML snippet is. It's easy to understand the hierarchy of the controls. There's another benefit when using XAML. We can directly see the result of our changes in Visual Studio through the design preview pane, which is usually positioned on the left in Visual Studio.

C#

Let's see how we can implement the same user interface using C# instead of XAML.

//Create Our StackPanel
StackPanel stackPanel = new StackPanel();
this.Content = stackPanel;

//Create Our TextBlock
TextBlock textBlock = new TextBlock();
textBlock.Margin = new Thickness(10);
textBlock.Text = "A Simple TextBlock";
stackPanel.Children.Add(textBlock);

//Create Our Button
Button button = new Button();
button.Margin= new Thickness(20);
button.Content = "Simple Button";
stackPanel.Children.Add(button);

As you can see, it's a bit clunkier in comparison to XAML and we're unable to see the result of our changes on the fly. You may also have noticed that the code block in C# is almost double the lines of code and it isn't as readable as the XAML snippet we saw earlier.

For Windows Phone development, XAML is the recommended way to create user interfaces. However, there may be times that we need to implement more complicated controls that are difficult to create using XAML, for example, when the control needs to be dynamic to some extent. Even though these situations are less common, it's good to know that we can fall back on C#.

Conclusion

XAML is an integral part of Windows Phone development and a firm understanding is therefore essential. I encourage you to take a look at the official XAML documentation from Microsoft on the Windows Phone Dev Center. It contains in-depth information about the use of XAML for Windows Phone development.

In this tutorial, we've taken a look at the role of XAML in Windows Phone development and how it compares to C# to create user interfaces. In the next tutorial, we'll continue to work with XAML and come to grips with some of the more common Windows Phone controls, their use, and how to implement them in a Windows Phone 8 application.

2014-09-03T16:30:37.000Z2014-09-03T16:30:37.000ZSani Yusuf

Enhanced and Wearable-Ready Notifications on Android

$
0
0
tag:code.tutsplus.com,2005:PostPresenter/cms-21868

Introduction

Notifications are a very useful way to interact with your application's users and, with Android Wear, we now also have wearable devices running Android. It's therefore a good idea to learn how to take advantage of these new features by adding appropriate actions to notifications or by creating actions that are only visible on wearable devices.

In this tutorial, I'm going to show you the modern implementation of notifications, as shown during this year's Google I/O. We'll use the new support package and extend its capabilities by adding actions that are only visible on smartwatches, the only wearable devices available with Android Wear at the time of writing.

1. Prerequisites

For this project, you can use either Android Studio or the Android Developer Tools. If you're using Android Studio, then make sure to add the following line to your build.gradle file.

compile "com.android.support:support-v4:20.0.+"

2. Setting Up the Project

Launch your IDE and create a new Android project, or open a project you've created previously. For this tutorial, I'm going to create a new project and name itImprovedNotifications. Don't forget to use a unique package name.

While setting up the project, make sure that you select the Empty Activity option in the Create Activity step.

Once the project is created, create a new Activity, ActivatedActivity. This Activity is going to be called from a notification on your mobile or wearable device.

Before we move on, we need to update the strings.xml file by adding the strings that we're going to be using a bit later in this tutorial.

<?xml version="1.0" encoding="utf-8"?><resources><string name="app_name">ImprovedNotifications</string><string name="title_activity_activated">ActivatedActivity</string><string name="message">Hi"!" I"'"m the activated activity</string><string name="button_text">Try me for a new notification</string><string name="notification_title">Hey Mom"!" I"'""m a title</string><string name="notification_text">Look at me"!" I"'"m a sexy notification content</string><string name="first_action">Let"'"s see the author"'"s twitter profile</string><string name="wearable_action">I only appear here</string></resources>

3. Creating the Layout

The next step is to create a layout for the MainActivity and the ActivatedActivity classes. The layout for the MainActivity class is shown below.

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="${relativePackage}.${activityClass}" ><Button
        android:id="@+id/notification_button"
        android:layout_height="wrap_content"
        android:layout_width="wrap_content"
        android:layout_centerInParent="true"
        android:padding="10dp"
        android:text="@string/button_text"/></RelativeLayout>

And this is the layout for the ActivatedActivity class.

<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"
    tools:context="${relativePackage}.${activityClass}" ><TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:padding="10dp"
        android:layout_centerInParent="true"
        android:text="@string/message"/></RelativeLayout>

4. Creating a Notification

We create a notification in the MainActivity class. In the code snippet below, you can see what steps are involved in creating a notification. I've commented the code block to help you understand the various steps, but let's walk through the snippet step by step.

package com.androiheroes.improvednotifications;

import android.app.Activity;
import android.app.Notification;
import android.app.PendingIntent;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.NotificationCompat;
import android.support.v4.app.NotificationManagerCompat;
import android.view.View;
import android.widget.Button;

public class MainActivity extends Activity {

    /* Widgets you are going to use */
  private Button button;
  
  /* 
   * This is the notification id 
   * You can use it to dismiss the notification calling the .cancel() method on the notification_manager object 
   */
  private int notification_id = 1;
  private final String NOTIFICATION_ID = "notification_id";
  
  /* These are the classes you use to start the notification */
  private NotificationCompat.Builder notification_builder;
  private NotificationManagerCompat notification_manager;
  
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    
    /* 
     * Step 1
     * Instantiation of the button you use to start the notification 
     */
    button = (Button) findViewById(R.id.notification_button);
    
    /* 
     * Step 2
     * Create the intent you are going to launch when your notification is pressed 
     * and let the PendingIntent handle it 
     */
    Intent open_activity_intent = new Intent(this, ActivatedActivity.class);
    open_activity_intent.putExtra(NOTIFICATION_ID, notification_id);
    PendingIntent pending_intent = PendingIntent.getActivity(this, 0, open_activity_intent, PendingIntent.FLAG_CANCEL_CURRENT);
        
    /* 
     * Step 3
     * Here you create the notification and start adding all the attributes you are going to use 
     */
    notification_builder = new NotificationCompat.Builder(this)
      .setSmallIcon(R.drawable.ic_launcher)
      .setContentTitle(getString(R.string.notification_title))
      .setContentText(getString(R.string.notification_text))
      /* 
       * This method specifies that our notification must have all the default characteristics of a notification 
       * like sound and vibration 
       */
      .setDefaults(Notification.DEFAULT_ALL)
      /* This method is going to dismiss the notification once it is pressed */
      .setAutoCancel(true)
      .setContentIntent(pending_intent);
    
    /* 
     * Step 4
     * Here we instantiate the Notification Manager object to start/stop the notifications 
     */
    notification_manager = NotificationManagerCompat.from(this);
  }
  
  @Override
  protected void onStart() {
    super.onStart();
    
    /* 
     * Step 5 
     * The notification is going to appear when you press the button on the screen 
     */
    button.setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View v) {
        notification_manager.notify(notification_id, notification_builder.build());
      }
    });
  }
}

Step 1

We first instantiate the button that we'll use to launch the notification. You could also create the notification directly in the onCreate method, but by using a button you have more control over the exact timing of the notification.

Step 2

In the second step, we instantiate an Intent object with the task to perform when the notification is tapped. We pass the object to a PendingIntent instance to handle it later when it's called.

Step 3

Using the Android Support Library, we create the notification using the Builder class of the NotificationCompat object and set its attributes.

Step 4

In this step, we instantiate a NotificationManagerCompat instance to start and/or stop the notification anytime we want. This will make testing much easier.

Step 5

When the button is tapped, the notification is fired using the notify method.

Don't forget to use the classes from the Android Support Library. This way you can be sure your notification is going to look fine on older versions of Android.

You can now run the app, tap the button, and see the notification appear at the top of the screen. If you tap the notification, it should take you to the ActivatedActivity activity. With the notification set up and working, it's time to start adding actions to it.

5. Adding Actions to the Notification

You can add extra actions to the notification by invoking the addAction method on the notification_builder object. For this to work, you need to pass a PendingIntent instance with the task you like to perform.

In the following code snippet, I show you the steps you have to implement to create an action with a custom task. In this example, I'm going to take you to my Twitter profile in the Twitter app. This means I need a URI instance pointing to my Twitter profile, add this to the Intent, and let the PendingIntent handle it when the action is tapped. Insert this code block before the instantiation of the notification_builder object.

 /* The action in the handheld notification must perform some task
  * In this case the author's twitter profile is going to be opened, in the twitter app, when it is clicked
  * but you can change it with your profile if you want ;) 
  */
  Intent open_twitter_profile = new Intent(Intent.ACTION_VIEW);
  Uri twitter_profile_location = Uri.parse("twitter://user?screen_name=@kerpie");
  open_twitter_profile.setData(twitter_profile_location);
  PendingIntent twitter_intent = PendingIntent.getActivity(this, 0, open_twitter_profile, 0);

To add the action, invoke the addAction method on the notification_builder object and pass in the open_twitter_profile object we just created.

/* 
 * Here you create the notification and start adding all the attributes 
 * you are going to use 
 */
notification_builder = new NotificationCompat.Builder(this)
	.setSmallIcon(R.drawable.ic_launcher)
	.setContentTitle(getString(R.string.notification_title))
	.setContentText(getString(R.string.notification_text))
	/*
	 * This method specifies that your notification must have all the default characteristics of a notification 
	 * like sound and vibration 
	 */			 
	.setDefaults(Notification.DEFAULT_ALL)
	/* This method is going to dismiss the notification once it is pressed */
	.setAutoCancel(true)
	.setContentIntent(pending_intent)
	/*
	 * Here you can add actions to your handheld device 
	 * just take care of the quantity of actions you add 
	 * in this case, like in many others, less is more 
	 */
	.addAction(android.R.drawable.ic_dialog_info, getString(R.string.first_action), twitter_intent);

Run the application, tap the button to trigger the notification, and you should see the notification appear along with the action we just created.

While you can add more actions to a notification using the addAction method, make sure the user isn't overwhelmed by the number of actions they can choose from.

6. Supporting Android Wear

So far, we have used the classes from the Android Support Library to make sure the notifications are also shown on smartwatches running Android Wear. You can run the application on a physical smartwatch or you can try it on the emulator from the Android Virtual Device Manager. Either way, you need to sync your device with the smartwatch.

Before syncing your device with the smartwatch emulator, you need to install the Android Wear app, which is available on Google Play. After you've unplugged every other Android device connected to your computer, execute the following command from the command line.

adb devices

This command lists the devices connected to your development machine. You should see two of them, the smartwatch emulator and your device. Then run the following command from the command line to enable port forwarding.

adb -d forward tcp:5601 tcp:5601

You can now connect your device with the emulator and turn on the notifications using the Android Wear app. Run the app again and trigger the notification. The notification should look similar to the one shown below.

7. Adding Wearable-Only Actions

It is possible to add actions that are only visible on wearables. This is accomplished by invoking the addAction method of the WearableExtender class. The result is that any actions added through the NotificationCompat.Builder class are ignored.

As we did before, to trigger the action, we make use of an Intent and a PendingIntent instance, but we'll create the action displayed on the wearable device using the Builder class of a special Action class, which is part of the NotificationCompat class as shown below.

/* Here we instantiate the Intent we want to use when the action in the smartwatch is pressed */
Intent wearable_intent = new Intent(this, ActivatedActivity.class);
PendingIntent wearable_pending_intent = PendingIntent.getActivity(this, 0, wearable_intent, PendingIntent.FLAG_UPDATE_CURRENT);

/* Now we have an intent for the wearable created we have to create a wearable action using it*/
NotificationCompat.Action wearable_action = new NotificationCompat.Action.Builder(
		android.R.drawable.ic_dialog_email, 
		getString(R.string.wearable_action), 
		wearable_pending_intent).build();

We then add this action to the notification_builder object using the extend method as shown below.

/* 
 * Here you create the notification and start adding all the attributes 
 * you are going to use 
 */
notification_builder = new NotificationCompat.Builder(this)
    .setSmallIcon(R.drawable.ic_launcher)
    .setContentTitle(getString(R.string.notification_title))
	.setContentText(getString(R.string.notification_text))
	/*
	 * This method specifies that your notification must have all the default characteristics of a notification 
	 * like sound and vibration 
	 */			 
	.setDefaults(Notification.DEFAULT_ALL)
	/* This method is going to dismiss the notification once it is pressed */
	.setAutoCancel(true)
	.setContentIntent(pending_intent)
	/*
	 * Here you can add actions to your handheld device 
	 * just take care of the quantity of actions you add 
	 * in this case, like in many others, less is more 
	 */
	.addAction(android.R.drawable.ic_dialog_info, getString(R.string.first_action), twitter_intent)
    /* 
     * Here you add a wearable-only action 
     * This action won't be visible in the handheld device 
     */
	.extend(new WearableExtender().addAction(wearable_action));

Run the app and tap the button to display the notification on your device. It should be different than the notification that pops up on the wearable emulator.

Conclusion

Smartwatches are here to stay, for a while at least, and it's therefore important to take advantage of this new way of communicating with your application's users. I hope you've found the tutorial helpful and don't forget to share it if you liked it.


2014-09-05T16:45:38.000Z2014-09-05T16:45:38.000ZKerry Perez Huanca

Core Data from Scratch: Subclassing NSManagedObject

$
0
0
tag:code.tutsplus.com,2005:PostPresenter/cms-21880

1. Introduction

Earlier in this series, we created Done, a simple application to learn more about the NSFetchedResultsController class. In that project, we used key value coding (KVC) and key value observing (KVO) to create and update records. This works fine, but from the moment your project has any kind of complexity, you'll quickly run into issues. Not only is the KVC syntax verbose, valueForKey: and setValue:forKey:, it may also introduce errors that are the result of typos. The following code snippet is a good example of the latter problem.

[record setValue:[NSDate date] forKey:@"createdat"];
[record setValue:[NSDate date] forKey:@"CreatedAt"];
[record setValue:[NSDate date] forKey:@"createdAt"];
[record setValue:[NSDate date] forKey:@"CREATEDAT"];

Each statement in the above code snippet returns a different result. In fact, every statement will result in an exception apart from the third statement, which uses the correct key as specified in the project's data model.

The above problem is easily solved by using string constants, but that's not the point I'm trying to make. Key value coding is great, but it is verbose and difficult to read if you're used to Objective-C's dot syntax. To make working with NSManagedObject instances easier, it's better to create an NSManagedObject subclass for each entity of the data model and that's what you'll learn in this article.

2. Subclassing NSManagedObject

To save some time, we're going to revisit Done, the application we created earlier in this series. Download it from GitHub and open it in Xcode.

Creating an NSManagedObject subclass is very easy. While it's possible to manually create an NSManagedObject subclass for an entity, it's easier to let Xcode do the work for you.

Open the project's data model, Done.xcdatamodeld, and select the TSPItem entity. Select New > File... from Xcode's File menu, choose the NSManagedObject subclass template from the Core Data section, and click Next.

Check the checkbox of the correct data model, Done, from the list of data models and click Next.

In the next step, you are asked to select the entities for which you want to create an NSManagedObject subclass. Check the checkbox of the TSPItem entity and click Next.

Choose a location to store the class files of the NSManagedObject subclass and make sure that Use scalar properties for primitive data types is unchecked. I'll explain the meaning of this option in a few moments. Click Create to create the NSManagedObject subclass for the TSPItem entity.

3. NSManagedObject Anatomy

Interface

Navigate to the files Xcode created for you and take a look at their contents. The header file, TSPItem.h, should look similar to what is shown below.

#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>

@interface TSPItem : NSManagedObject

@property (nonatomic, retain) NSDate * createdAt;
@property (nonatomic, retain) NSNumber * done;
@property (nonatomic, retain) NSString * name;

@end

At the top, you should see import statements for the Foundation and the Core Data frameworks. The NSManagedObject subclass contains three properties, corresponding with the attributes of the TSPItem entity of the data model. There are a few differences though.

The types of the name and createdAt properties, NSString, isn't surprising. The type of the done property, however, is less obvious. Even though we declared the type of the done attribute as a boolean in the data model, the done property is of type NSNumber. The reason is simple. When we created the NSManagedObject subclass a few moments ago, we left the checkbox labeled Use scalar properties for primitive data types unchecked. If we had checked that checkbox, the done property would be of type BOOL.

While it's up to you to decide whether you want to work with objects or primitive data types, there is a reason why the checkbox is unchecked by default. You'll quickly find out that it's less convenient to use primitive data types for the properties of an NSManagedObject subclass. It may look good on paper, but it becomes a hassle when you, for example, want to store primitive data types in Objective-C collections, which only accept objects.

Implementation

The implementation of the TSPItem class is even shorter and it uses a compiler directive that may be new to you.

#import "TSPItem.h"

@implementation TSPItem

@dynamic createdAt;
@dynamic done;
@dynamic name;

@end

By using the @dynamic directive, the compiler knows that the accessors (getters and setters) for the properties declared in the class's interface will be generated at runtime. The compiler takes our word for it and doesn't issue any warnings.

If you comment out the @dynamic statements, the compiler generates three warnings, telling us that the accessors for the three properties are missing.

4. Updating the Project

With the TSPItem class ready to use, it's time to update the project by replacing any occurrences of valueForKey: and setValue:forKey:.

TSPViewController

Open the implementation file of the TSPViewController class and start by adding an import statement for the TSPItem class at the top.

#import "TSPItem.h"

Navigate to the configureCell:atIndexPath: and update the implementation as shown below.

- (void)configureCell:(TSPToDoCell *)cell atIndexPath:(NSIndexPath *)indexPath {
    // Fetch Record
    TSPItem *record = [self.fetchedResultsController objectAtIndexPath:indexPath];
    // Update Cell
    [cell.nameLabel setText:record.name];
    [cell.doneButton setSelected:[record.done boolValue]];
    [cell setDidTapButtonBlock:^{
        BOOL isDone = [record.done boolValue];
        // Update Record
        record.done = @(!isDone);
    }];
}

We've made five changes. We first changed the type of the record variable to TSPItem. The objectAtIndexPath: method of the NSFetchedResultsController class returns an instance of the NSManagedObject class. This is still true since the TSPItem class is a NSManagedObject subclass.

We also substitute the valueForKey: calls. Instead, we use the properties of the record object, name and done. Thanks to Objective-C's dot syntax, the result is very legible. Note that we call boolValue on the record's done property. Remember that the done property is of type NSNumber, which is why we need to call boolValue on it to get the actual boolean value. To set the value of the isDone variable, we repeat this step.

To update the record, we no longer call setValue:forKey:. Instead, we use the dot syntax to set the record's done property. I'm sure you agree that this is much more elegant than using straight key value coding.

Remember that KVC and KVO remain an integral part of Core Data. Core Data uses valueForKey: and setValue:forKey: under the hood to get the job done.

TSPAddToDoViewController

We also need to make a few changes in the TSPAddToDoViewController class. Start by adding an import statement for the TSPItem class. In the save: method, we first need to update the initialization of the NSManagedObject instance. Instead of initializing an NSManagedObject instance, we create a TSPItem instance.

// Initialize Record
TSPItem *record = [[TSPItem alloc] initWithEntity:entity insertIntoManagedObjectContext:self.managedObjectContext];

To populate the record, we use the dot syntax instead of the setValue:forKey method as shown below.

// Populate Record
record.name = name;
record.createdAt = [NSDate date];

TSPUpdateToDoViewController

The last class we need to update is the TSPUpdateToDoViewController class. Let's start with the class's interface. Open TSPUpdateToDoViewController.h and update its contents as shown below. We add a forward class declaration for the TSPItem class at the top and change the type of the record property to TSPItem.

#import <UIKit/UIKit.h>
#import <CoreData/CoreData.h>

@class TSPItem;

@interface TSPUpdateToDoViewController : UIViewController

@property (weak, nonatomic) IBOutlet UITextField *textField;

@property (strong, nonatomic) NSManagedObjectContext *managedObjectContext;

@property (strong, nonatomic) TSPItem *record;

@end

This change will result in a warning in the TSPViewController class. To see what's wrong, open the implementation file of the TSPViewController class and navigate to the prepareForSegue:sender: method.

We ask the fetched results controller for the record at the selected index path, self.selection. The type of the record variable is NSManagedObject, but the TSPUpdateToDoViewController class expects a TSPItem instance. The solution is very simple as you can see below.

if (self.selection) {
    // Fetch Record
    TSPItem *record = [self.fetchedResultsController objectAtIndexPath:self.selection];
    if (record) {
        [vc setRecord:record];
    }
    // Reset Selection
    [self setSelection:nil];
}

Head back to the TSPUpdateToDoViewController class and add an import statement for the TSPItem class at the top of its implementation file. Update the viewDidLoad method as shown below.

- (void)viewDidLoad {
    [super viewDidLoad];
    if (self.record) {
        // Update Text Field
        [self.textField setText:self.record.name];
    }
}

We also need to update the save: method, in which we replace setValue:forKey: with the dot syntax.

// Populate Record
self.record.name = name;

Build the project and run the application in the iOS Simulator to see if everything is still working as expected.

5. Relationships

The current data model doesn't contain any relationships, but let's add a few to see how an NSManagedObject subclass with relationships looks like. As we've seen in the previous article of this series, we first need to create a new version of the data model. Select the data model in the Project Navigator and choose Add Model Version... from the Editor menu. Set Version name to Done 2 and base the model on the current data model, Done. Click Finish to create the new data model version.

Open Done 2.xcdatamodel, create a new entity named TSPUser, and add an attribute name of type String. Add a relationship items and set the destination to TSPItem. Leave the inverse relationship blank for now. With the items relationship selected, open the Data Model Inspector on the right and set the relationship type to To Many. A user can have more than one item associated with it.

Select the TSPItem entity, create a relationship user, and set the destination to TSPUser. Set the inverse relationship to items. This will automatically set the inverse relationship of the items relationship of the TSPUser entity.

Before we create the NSManagedObject subclasses for both entities, we need to tell the data model which data model version it should use. Select Done.xcdatamodeld, open the File Inspector on the right, and set the current model version to Done 2. When you do this, double-check that you've selected Done.xcdatamodeld, not Done.xcdatamodel.

Remove TSPItem.h and TSPItem.m from the project. Select New > File... from the File menu and choose the NSManagedObject subclass template from the Core Data section. From the list of data models, select Done 2.

Select both entities from the list of entities. Because we've modified the TSPItem entity, we need to regenerate the corresponding NSManagedObject subclass.

TSPItem

Let's first take a look at the changes of the newly generated TSPItem class. As you can see below, the header file contains one additional property, user of type TSPUser. To satisfy the compiler, Xcode also added a forward class declaration at the top.

#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>

@class TSPUser;

@interface TSPItem : NSManagedObject

@property (nonatomic, retain) NSDate * createdAt;
@property (nonatomic, retain) NSNumber * done;
@property (nonatomic, retain) NSString * name;
@property (nonatomic, retain) TSPUser *user;

@end

The implementation file reflects the addition of the user property.

#import "TSPItem.h"
#import "TSPUser.h"

@implementation TSPItem

@dynamic createdAt;
@dynamic done;
@dynamic name;
@dynamic user;

@end

This is what a To One relationship looks like in an NSManagedObject subclass. Xcode is smart enough to infer that the type of the user property is TSPUser, the NSManagedObject subclass we created a moment ago.

TSPUser

The TSPUser class is a bit more complex. Take a look at the class's interface. The first thing you'll notice is that the type of the items property is NSSet. This shouldn't be a surprise, because we already knew that Core Data uses the NSSet class for storing the members of a To Manyrelationship.

#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>

@class TSPItem;

@interface TSPUser : NSManagedObject

@property (nonatomic, retain) NSString * name;
@property (nonatomic, retain) NSSet *items;
@end

The header file of the TSPUser class also contains a class extension that includes four convenience methods. This is another benefit of using an NSManagedObject subclass and let Xcode generate it for us. Instead of directly manipulating the items property, we can add and remove TSPItem instances using these convenience methods.

@interface TSPUser (CoreDataGeneratedAccessors)

- (void)addItemsObject:(TSPItem *)value;
- (void)removeItemsObject:(TSPItem *)value;
- (void)addItems:(NSSet *)values;
- (void)removeItems:(NSSet *)values;

@end

Let me show you why these convenience methods are so useful. Let's see what it takes to add a TSPItem object to a TSPUser instance with and without these convenience methods.

/**
 *  With Convenience Methods
 */
[user addItemsObject:item];

/**
 *  Without Convenience Methods
 */
NSMutableSet *items = [[user items] mutableCopy];
[items addObject:item];
[user setItems:items];

Under the hood, however, Core Data uses key value coding to add the TSPItem instance to the items property of the user object.

NSMutableSet *items = [user mutableSetValueForKey:@"items"];
[items addObject:item];

6. Migrations

If you build the project and run the application in the iOS Simulator, you'll notice that the application crashes. The output in Xcode's console tells us that the data model used to open the persistent store is not compatible with the one that was used to create it. The reason of this problem is explained in detail in the previous article of this series. If you want to learn more about migrations and how to safely modify the data model, then I suggest you read that article.

Conclusion

Subclassing NSManagedObject is very common when working with Core Data. Not only does it add type safety, it also makes working with relationships much easier.

In the next installment of this series, we take a closer look at Core Data and concurrency. Concurrency is a tricky concept in almost any programming language, but knowing which pitfalls to avoid, makes it much less scary.

2014-09-08T17:45:14.000Z2014-09-08T17:45:14.000ZBart Jacobs

Windows Phone 8: Controls and Properties

$
0
0
tag:code.tutsplus.com,2005:PostPresenter/cms-20487

In this tutorial, you will be learning about some of the more popular Windows Phone controls. You will also be learning about the properties controls can have and see how they can be used to describe controls.

1. What are controls?

Controls are the building blocks of a Windows Phone application. There are many types of controls, differing in their functionality and how they look. For example, there are controls that we can use to contain and arrange other controls like the StackPanel and the Grid controls. There are also controls that we can use to build features of our application like the Button, TextBox and TextBlock controls. Everything you see in a Windows Phone application is a control in one way or another.

There is a wide range of controls included in the Windows Phone SDK. Let's take a look at some of the most common controls.

  • Button This is easily the most used control. As its name implies, this control is used to create a button and it detects gestures, such as tapping and holding.
  • TextBlock This is the control that you use when you want to display a block of text in a view.
  • TextBox Like the name suggests, with the TextBox control, the user can enter text. This is used to collect user input within a Windows Phone application.
  • StackPanel This control is used to collect or organize one or more other controls. The controls it contains can be arranged or stacked horizontally or vertically.
  • Grid A grid works very similar like an HTML Table. Other controls can be placed in it, arranged in rows and columns that we define.
  • LongListSelector This control lets us display a list of controls. For example, if we want to show a list of pictures or names in an application, then the LongListSelector is the best choice.

2. Sample Application

To get a better understanding of Windows Phone controls, we'll create a new Windows Phone project and play around with some of the controls listed above. To create a new Windows Phone 8 project, follow the same steps as outlined in Creating Your First Application.

In Visual Studio, you should see the design and the XAML views for the MainPage.xaml page. There should also be some menu options on to the left, one of which is the ToolBoxmenu. Open the ToolBox menu to see a list of controls that are included in the Windows Phone SDK.

In the list of controls, find the Button control and drop an instance of it onto the Visual Studio design preview. Do the same for the TextBlock and TextBox controls. You should now have something similar to what I have below.

3. Properties

Properties are values that we can use to customize or describe the look and feel of a control. Properties take the following format, Property="Value". For example, if you take a closer look at the XAML code of your project, you'll see that each control has a number of properties with corresponding values.

Take the Button you created as an example. If you want to edit the button's text, then you need to change the value of its Content property. To change the text of the TextBlock control, you change its Text property.

There are also properties that control the control's positioning, such as Margin and Padding properties. Visual Studio has a Properties tab that makes setting properties very easy. By default, the Properties tab is positioned at the bottom right, but that may be different for you and depends on how you've set up Visual Studio. 

The Properties menu comes in very handy when setting properties for a control, because it shows you what properties are available for a particular control.

4. StackPanel & Grid

The StackPanel and Grid controls are very important controls for building layouts in Windows Phone. Almost every application you'll build will make use of them so it's important to understand how they work.

As I mentioned earlier, the StackPanel and Grid controls contain other controls and arrange them in a particular way. If you have experience with HTML, then you can compare the StackPanel and Grid controls to HTML's div and table elements respectively.

StackPanel

The StackPanel control lets us arrange controls as a stack of items. The controls placed within a StackPanel can be arranged horizontally or vertically, depending on the value of its Orientation property.

Let's take look at the StackPanel control in action. If you refer back to our project's XAML view for theMainPage.xaml page, you should already see a StackPanel control holding two TextBlock instances that make up the header of the page.

<!--TitlePanel contains the name of the application and page title--><StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28"><TextBlock Text="MY APPLICATION" Style="{StaticResource PhoneTextNormalStyle}" Margin="12,0"/><TextBlock Text="page name" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/></StackPanel>

By default, the orientation of a StackPanel instance is set to vertical. We only need to set this property if we need a horizontal StackPanel. Play around with the StackPanel by changing its orientation to horizontal. To sum up, whenever you need to arrange controls linearly, the StackPanel control is probably what you're looking for.

Grid

Like the StackPanel, the Grid control arranges one or more controls. Unlike the StackPanel, the Grid control arranges its children using rows and columns, similar to an HTML table.

Let's take another look at our project's XAML view to see the Grid control in action. Our application already contains two Grid instances. The first one is the top level container of our application and it contains a second Grid instance.

From the image above, you can see that the first Grid, LayoutRoot, contains two rows, indicated by Grid.RowDefinition. The StackPanel named TitlePanel has a Grid.Row property set to 0, which tells it to occupy the first row of the Grid it is in.

The second Grid, ContentPanel, has its Grid.Row property set to 1, which means it's placed in the second row of the Grid it is in.

The Grid control is very useful when creating complex layouts. We won't be covering every aspect of the Grid control, but I encourage you to read more about it in the documentation.

5. LongListSelector

The LongListSelector control is a very powerful control that has a host of capabilities. The People application, shown below, is a good example of this control in action. We won't be covering the LongListSelector control in this article, but if you'd like to learn more about this powerful control, then have a look at the documentation.

 

Conclusion

In this tutorial, we covered some of the more common controls used in Windows Phone applications. We've learned about properties and other aspects of controls, and we taken a closer look at the StackPanel and Grid controls.

In the next tutorial, we'll be focusing on events on Windows Phone and how you can handle them.

2014-09-10T16:45:54.000Z2014-09-10T16:45:54.000ZSani Yusuf

Introduction to Android Wear: The Basics

$
0
0
tag:code.tutsplus.com,2005:PostPresenter/cms-22042

Introduction

In March 2014, Google officially announced they were branching out into the world of wearables with the unveiling of Android Wear, a new version of the Android operating system designed specifically for wearables. Fast forward a few months to the Google I/O event and Google unveiled two devices running Android Wear, the Samsung Gear Live and LG G Watch.

It's still early days for this new version of the Android operating system, but with more Android Wear devices on the horizon—both Motorola and HTC are launching their own Android smartwatches later this year—this is the perfect time to start getting to grips with this exciting new platform.

Over the course of this two-part series, you'll get an in-depth introduction to all things Android Wear, from the basics of what Android Wear is and how it works, right through to developing your own wearable-ready apps.

In the first part, you'll get all the background information and best practices you need, ready to start developing for the wearable platform in the second part.

1. What is Android Wear?

The Android Wear operating system uses Bluetooth to connect to handheld device(s) running Android 4.3 or higher. Once this connection is made, the wearable channels information and updates from the paired smartphone and/or tablet, and conveniently displays them on the user's wrist. These updates include things like Google Now cards, Gmail, Google Calendar, and phone notifications, such as incoming calls and text messages.

But, Android Wear is more than just a convenient way to receive smartphone and tablet notifications. Android Wear can also execute tasks on the paired smartphone or tablet. For example, you can use your Android Wear device to play, pause, and skip music tracks on your handheld.

Another big part of the Android Wear experience are vocal commands. Vocal commands allow you to retrieve information as well as execute tasks on the wearable and on the paired handheld device(s). When the user wants to issue a vocal command, all they need to say is "Okay, Google", followed by their command.

Tasks that Android Wear users can already complete using voice alone, include:

  • Sending texts, instant messages, and emails ("send Jessica Thornsby a text message," and then dictating your message).
  • Getting answers to those important questions in life, such as “will it rain this afternoon?” and “Where’s the nearest pub?”
  • Getting directions (“Give me directions to Tamper Coffee on West Street.”) The directions appear via Google Maps on the paired handheld device and as cards on the wearable. The Android Wear device also vibrates when it's time for you to make a turn.
  • Setting yourself reminders to trigger either at a certain time or when Android Wear detects you're at a specific location (“remind me to clean the rabbits out when I get home.”)
  • Taking notes using Google Keep ("take a note, we need more milk.")
  • Launching an app on the paired handheld ("Open Facebook.")

Although this connection means your wearable app can utilize lots of information and functionality from the paired handheld device, the downside is that you'll usually need to develop two versions of your app, one that runs on the wearable and one that runs on the handheld.

2. Understanding Android Wear's User Interface

The Android Wear operating system is very different from the operating system you’re used to seeing on tablets and smartphones. This difference is most prominent in terms of user interface.

Google has developed an entirely new user interface for Android Wear. For now, think of this new user interface in terms of its two major components, the Context Stream and the Cue Card.

Context Stream

Rather than quitting and launching apps as you would on a smartphone or tablet, the majority of wearable apps work around a card-based system.

The heart of the Android Wear user interface is a vertical stream of cards that appear automatically based on factors such as location, time, and the user's activity and interests. If you're familiar with Google Now, the Context Stream will feel instantly familiar as it resembles an automatically-ranked stream of Google Now cards.

Unlike the Google Now cards you're used to seeing on your smartphone or tablet, Android Wear only displays a single card at a time. The user scrolls between the currently-active cards by swiping vertically.

Example of a notification card on an Android Wear device

Although it's possible to develop full-screen apps for wearable devices, Google are encouraging developers to integrate their wearable apps with the Context Stream as much as possible.

Your goal should be to create an app that generates cards and then inserts these cards into the Context Stream at the point they become most useful. The user can then glance at the stream and immediately see your app's timely and relevant update.

You also have the option to add extra pages of information to your notification card. The user accesses these pages by swiping right on the notification card.

The screenshots below show a weather notification card that displays today's forecast and an additional page that displays the forecast for subsequent days.

A weather notification card on the Android Wear platform The 

The above screenshot shows the main notification card.

Example of an additional page on an Android Wear device The 

The above screenshot shows an additional page.

If the user continues to swipe through the extra pages, they may encounter another common user interface element, an action button. As the name suggests, action buttons allow the user to perform an action, which may occur on the wearable or on the paired handheld device£.

Cue Card

Sometimes, the user won't get the information they need from the notification card(s) alone or they'll want to perform a specific task. In these situations, the user can tell Android Wear what they want by issuing a vocal command.

When the user gives the "Okay, Google" wake-up command, what they're actually doing is launching a special "Cue Card" that receives and acts on their vocal commands.

An Android Wear Cue Card

This may sound straightforward, but the Cue Card opens up some interesting possibilities for the developer.

When the Cue Card recognizes and acts upon a vocal command, what's actually happened is that the Cue Card has successfully matched the vocal command to a specific Intent. The key to getting your app to respond to vocal commands is to hook into these Intents.

3. Android Wear Libraries and Classes

The Android Wear APIs are delivered via Google Play services and the Android Support Library. This is a broad topic that's worth exploring in-depth, but there's a couple of libraries and classes that are worth getting acquainted with straight away.

Android Support Library & NotificationCompat

The easiest way to start developing for wearables is to create a handheld app that can send notifications to a paired wearable device.

Extending your notifications in this way requires several classes, which you can find in the Android v4 Support Library:

  • NotificationCompat.WearableExtender: This class allows you to add wearable-specific extensions to your notifications, which is essential for providing users with the best possible Android Wear experience.
  • NotificationCompat.Builder: This builder class ensures your notifications display properly, both on handheld and wearable devices.
  • NotificationManagerCompat: This class ensures your notifications properly support wearable features. When it's time to deliver your notifications, make sure you use NotificationManagerCompat instead of NotificationManager. If you do use NotificationManager, it's possible some NotificationCompat.WearableExtender features won't function properly.
  • NotificationCompat.Action.WearableExtender: This class extends notification actions to wearables. Each action must have a title, an icon that represents the action, and an Intent that's sent whenever the user invokes the action.

To add the Android v4 Support Library to your development environment, open the Android SDK Manager, and then download and install either the Android Support Library package (if you’re an Eclipse user) or Android Support Repository (if you're on Android Studio).

The Android SDK Manager

Wearable User Interface Support Library

This unofficial library helps you design a wearable-friendly user interface for your app by including user interface widgets that illustrate best practices.

One particularly important component of this support library, is the BoxInsetLayout layout manager, which lets you use the same layout on both rectangular and round screens.

If you're using Android Studio, then this library is automatically included when you use the Project Wizard to create a wearable app.

4. Best Practices

Before you fire up your development environment and put what you've just learnt into practice, it's important you know what makes a great Android Wear app, so you can create the best possible experience for your users.

In the second part of this two-part series, we'll look at the best practices you should keep in mind when you're developing Android Wear apps.

Create a Glanceable App

The key to developing a great Android Wear app is to keep questioning how you would use a traditional watch. Do you stare at your watch's face for any significant length of time? Or do you just glance at it and expect to get all the information you need?

The user will expect to interact with their smartwatch—and by extension your app—in exactly the same way as their normal watch. Therefore, a big part of designing a successful wearable app is to make it as glanceable as possible. To design a glanceable app and notification cards, keep the following guidelines in mind.

Display One Piece of Information at a Time

Your notification cards should only ever display a single piece of information. If you need to communicate more information, use additional pages rather than trying to squeeze more info onto a single card.

Keep Text to a Minimum

Your notification card should only contain words and phrases, not complete sentences. A trick for keeping text to a minimum is to communicate each piece of information through an icon and value pairing. For example, a glanceable alternative to the sentence "There's a 50% chance of rain today," is a cloud-and-raindrop icon accompanied by a "50%" label.

Increase Font Size

Make your text easier to read at a glance, and at a distance, by increasing the font size. When you use a large font, you'll also be less tempted to pack more information onto a single card.

Make Use of Background Images

As the old saying goes, a picture is worth a thousands words. You can instantly communicate crucial information about a notification card by including a background image.

A particularly effective use of background images is to provide a selection of images that correspond to the different notifications your app can generate. For example, if you're designing an app that notifies the user about traffic jams along their most frequently-used routes, it makes sense to supply three different background images, an open road, a few cars, and a massive traffic jam. Then, whenever your app generates a card, it can choose the most appropriate background image to accompany that card. Even if the user is too busy to examine your notification card in detail, they can still get some useful information from the background image alone.

Example of a notification card with an eye-catching background image

Keep Interactions Simple

Again, consider how you use a normal watch. When was the last time you sat down and gave your watch a few minutes of your undivided attention?

Watches are designed to be glanced at on the go, in-between performing other activities. Smartwatches, and by extension wearable apps, are no different. Users expect their wearable app to provide the information they need, without them having to navigate various menus and tap different options.

With this in mind, your app should require user input only when it's absolutely necessary. On the rare occasions where you do need some input from the user, you should focus on quick and easy interactions such as taps, swipes, and voice commands, as anything more complicated is difficult for the user to achieve on a wearable's smaller screen.

If your app really does require a more complicated interaction, don't force the user to complete this interaction on the wearable. Instead, transfer the user to the paired handheld device, where they can complete the interaction on a larger screen, before returning to their wearable.

In the screenshot below, tapping the action button will launch the relevant app on the user's paired smartphone, where they can complete the interaction in question.

Example of an Android Wear action button

Keep Active Notifications to a Minimum

Wearables, as the name suggests, are worn against the skin. This means that active notifications—notifications that cause the device to vibrate—are difficult to ignore and almost impossible to miss.

This has some obvious benefits. For example, when you pair a wearable to your smartphone, you no longer have to worry about missing an important call because your phone is in the bottom of your bag. However, because active notifications are almost impossible to ignore, a wearable app that's constantly triggering active notifications is going to become very irritating, very quickly.

As a general rule, your wearable app should only trigger active notifications when the notification in question involves a contact and is occurring now, for example, the paired smartphone is receiving a text message. When this isn't the case, your app should instead generate a card and insert it into the Context Stream, ready for the next time the user glances at their wearable.

At the very least, make sure your wearable app is using less active notifications than its smartphone or tablet equivalent.

Conclusion

In the first part of this two-part series, you got an in-depth introduction to the Android Wear operating system and what it has to offer both users and developers. You've also learned a number of best practices for developing great wearable apps.

In the second part, I'll show you how setup your development environment and start developing for the Android Wear platform.

2014-09-12T17:45:30.000Z2014-09-12T17:45:30.000ZJessica Thornsby

Windows Phone 8: Events and Navigation

$
0
0

In this tutorial, I'll be teaching you about the event model of Windows Phone. More importantly, we'll learn about navigation and how we can add it to an application to allow users to navigate between pages of a Windows Phone application.

1. Events

Events in Windows Phone are simply actions that are triggered after a specific condition has been satisfied. This action is normally initiated by user interaction. A good example of an event is the user tapping a button in a Windows Phone application. The user would normally expect something to happen after tapping a button. Right?

Controls can have many events attached to them. On Windows Phone, we can specify a code block to be executed when a particular event occurs. This process is called event handling. We can also create custom events, but that is beyond the scope of this tutorial. Instead, we'll explore some of the built-in events that some Windows Phone controls respond to.

2. Event Handling

Event handling is fairly easy on Windows Phone. We even have the possibility to define even handlers in XAML, similar to how we define properties. Let's see how this works.

Start by creating a new Windows Phone C# project like we've done in the previous tutorials. In your new project, drag aButton control from the ToolBox onto the blank space in the Visual Studio  design view. You should have something that looks like what I have below.

To demonstrate how events work, we are going to have our application display a simple Hello World popup message when the user taps the button we just added. A Button control has a Click event, which we can subscribe to and handle.

To see the events a control possesses, select the control in the design view and go to the Visual Studio properties window at the bottom right. Click the events button in the top right of the window to show the control's events.


You should see a list of events for the selected control. These events are the built-in events of the currently selected control. In the text field on the right of each event, we can specify the name of a method that is invoked when the event occurs. That method is the event handler.

In other words, the event handler is invoked when the event occurs. The event that interests us at this point is the Click event. Double-click the text field on the right of the event name This should automatically bring you to the MainPage.cs class that is coupled with our MainPage.xaml page. You should also see an auto-generated method, which represents the event handler, named Button_Click or something similar.

Remember that for every XAML page we create in Windows Phone is coupled with a C# page which contains the code for the controls created in the XAML page. This C# code is normally referred to as code behind.

Now, let's go ahead and implement the code to display a message saying "Hello World". Add the following code snippet to the Button_Click method as shown below.

private void Button_Click(object sender, RoutedEventArgs e) {
    MessageBox.Show("Hello World");
}

This is all we need to do to implement the click event handler for our button. Before we test our application, let me explain what the above code snippet does. The MessageBox class is part of the .NET library and allows us to show a popup message. By calling the Show method on the MessageBox class and passing in a string, "Hello World", a popup is shown to the user. Run the application and tap the button to see the result of our work.

That was easy, wasn't it? Events are an integral part of a Windows Phone application and you'll find yourself using them frequently when developing Windows Phone applications.

3. Navigation

Now that we know about events and event handling, it's time to learn about another important aspect of Windows Phone, navigation. Most Windows Phone applications have more than one page and we need to implement a way to navigate between these pages.

Windows Phone takes a very simple approach to navigation, allowing us to navigate from one page to another with very little work. The way navigation works on Windows Phone is very similar to how you navigate web pages. We make use of a URI or Universal Resource Identifier, which is very similar to a URL in web development. With URIs, you can even pass parameters, just like you can on the web. We won't cover this aspect of navigation in this tutorial though.

Let's explore navigation by expanding our current application. We first need to create a new page to which we can navigate. Right-click your project's name in the Solution Explorer and select Add > Add Item from the menu. Create a page named Page1.xaml.

Add a TextBlock control to the new page and set its text to "This Is a New Page" by changing the Text property.

The goal is to navigate from the first page, MainPage.xaml, to the new page, Page1.xaml. To accomplish this, we need to edit the event handler of the button on the first page. Instead of displaying a popup message, we navigate to the page we just created. Open MainPage.cs and locate the event handler we created a moment ago. Replace its implementation with the one shown below.

private void Button_Click(object sender, RoutedEventArgs e) {
    NavigationService.Navigate(new Uri("/Page1.xaml", UriKind.Relative));
}

In the even handler, we call the Navigate method on the NavigationService class, passing in an instance of the Uri class. The NavigationService class is accessible from every Windows Phone page, allowing us to navigate to another page.

The Navigate method takes a Uri instance as a parameter. We create the Uri object by passing two parameters. The first parameter is the relative path to the page we want to navigate to, /Page1.xaml in our example. It's important to add the leading forward slash when navigating to a relative path. The second parameter we pass is the type of Uri we are passing, UriKind.Relative in this example. It indicates that first parameter is a relative path.

We don't need to create a back button, because every Windows Phone device has a physical back button that takes the user to the previous page. However, we could override the default behavior of the back button if we really wanted to.

Run your application one more time and tap the button on the first page to navigate to the second page. If you've followed the steps in this tutorial, the application should take you to the next page as shown below.

As you can see, it's very easy to navigate between pages in a Windows Phone application. I encourage you to explore the documentation to learn more about Windows Phone events and navigation.

Conclusion

In this tutorial, you learned the basics of Windows Phone events and how to handle events. You also learned about navigation on Windows Phone.

In the next tutorial, I will be showing you how to add media elements, such as audio and images, to a Windows Phone application.

2014-09-15T16:28:25.101Z2014-09-15T16:28:25.101ZSani Yusuf

Windows Phone 8: Events and Navigation

$
0
0
tag:code.tutsplus.com,2005:PostPresenter/cms-20493

In this tutorial, I'll be teaching you about the event model of Windows Phone. More importantly, we'll learn about navigation and how we can add it to an application to allow users to navigate between pages of a Windows Phone application.

1. Events

Events in Windows Phone are simply actions that are triggered after a specific condition has been satisfied. This action is normally initiated by user interaction. A good example of an event is the user tapping a button in a Windows Phone application. The user would normally expect something to happen after tapping a button. Right?

Controls can have many events attached to them. On Windows Phone, we can specify a code block to be executed when a particular event occurs. This process is called event handling. We can also create custom events, but that is beyond the scope of this tutorial. Instead, we'll explore some of the built-in events that some Windows Phone controls respond to.

2. Event Handling

Event handling is fairly easy on Windows Phone. We even have the possibility to define even handlers in XAML, similar to how we define properties. Let's see how this works.

Start by creating a new Windows Phone C# project like we've done in the previous tutorials. In your new project, drag aButton control from the ToolBox onto the blank space in the Visual Studio  design view. You should have something that looks like what I have below.

To demonstrate how events work, we are going to have our application display a simple Hello World popup message when the user taps the button we just added. A Button control has a Click event, which we can subscribe to and handle.

To see the events a control possesses, select the control in the design view and go to the Visual Studio properties window at the bottom right. Click the events button in the top right of the window to show the control's events.


You should see a list of events for the selected control. These events are the built-in events of the currently selected control. In the text field on the right of each event, we can specify the name of a method that is invoked when the event occurs. That method is the event handler.

In other words, the event handler is invoked when the event occurs. The event that interests us at this point is the Click event. Double-click the text field on the right of the event name This should automatically bring you to the MainPage.cs class that is coupled with our MainPage.xaml page. You should also see an auto-generated method, which represents the event handler, named Button_Click or something similar.

Remember that for every XAML page we create in Windows Phone is coupled with a C# page which contains the code for the controls created in the XAML page. This C# code is normally referred to as code behind.

Now, let's go ahead and implement the code to display a message saying "Hello World". Add the following code snippet to the Button_Click method as shown below.

private void Button_Click(object sender, RoutedEventArgs e) {
    MessageBox.Show("Hello World");
}

This is all we need to do to implement the click event handler for our button. Before we test our application, let me explain what the above code snippet does. The MessageBox class is part of the .NET library and allows us to show a popup message. By calling the Show method on the MessageBox class and passing in a string, "Hello World", a popup is shown to the user. Run the application and tap the button to see the result of our work.

That was easy, wasn't it? Events are an integral part of a Windows Phone application and you'll find yourself using them frequently when developing Windows Phone applications.

3. Navigation

Now that we know about events and event handling, it's time to learn about another important aspect of Windows Phone, navigation. Most Windows Phone applications have more than one page and we need to implement a way to navigate between these pages.

Windows Phone takes a very simple approach to navigation, allowing us to navigate from one page to another with very little work. The way navigation works on Windows Phone is very similar to how you navigate web pages. We make use of a URI or Universal Resource Identifier, which is very similar to a URL in web development. With URIs, you can even pass parameters, just like you can on the web. We won't cover this aspect of navigation in this tutorial though.

Let's explore navigation by expanding our current application. We first need to create a new page to which we can navigate. Right-click your project's name in the Solution Explorer and select Add > Add Item from the menu. Create a page named Page1.xaml.

Add a TextBlock control to the new page and set its text to "This Is a New Page" by changing the Text property.

The goal is to navigate from the first page, MainPage.xaml, to the new page, Page1.xaml. To accomplish this, we need to edit the event handler of the button on the first page. Instead of displaying a popup message, we navigate to the page we just created. Open MainPage.cs and locate the event handler we created a moment ago. Replace its implementation with the one shown below.

private void Button_Click(object sender, RoutedEventArgs e) {
    NavigationService.Navigate(new Uri("/Page1.xaml", UriKind.Relative));
}

In the even handler, we call the Navigate method on the NavigationService class, passing in an instance of the Uri class. The NavigationService class is accessible from every Windows Phone page, allowing us to navigate to another page.

The Navigate method takes a Uri instance as a parameter. We create the Uri object by passing two parameters. The first parameter is the relative path to the page we want to navigate to, /Page1.xaml in our example. It's important to add the leading forward slash when navigating to a relative path. The second parameter we pass is the type of Uri we are passing, UriKind.Relative in this example. It indicates that first parameter is a relative path.

We don't need to create a back button, because every Windows Phone device has a physical back button that takes the user to the previous page. However, we could override the default behavior of the back button if we really wanted to.

Run your application one more time and tap the button on the first page to navigate to the second page. If you've followed the steps in this tutorial, the application should take you to the next page as shown below.

As you can see, it's very easy to navigate between pages in a Windows Phone application. I encourage you to explore the documentation to learn more about Windows Phone events and navigation.

Conclusion

In this tutorial, you learned the basics of Windows Phone events and how to handle events. You also learned about navigation on Windows Phone.

In the next tutorial, I will be showing you how to add media elements, such as audio and images, to a Windows Phone application.

2014-09-15T16:28:25.101Z2014-09-15T16:28:25.101ZSani Yusuf

iOS 8: Integrating Touch ID

$
0
0
tag:code.tutsplus.com,2005:PostPresenter/cms-21949

In September 2013, Apple unveiled the latest iPhone with a range of hardware improvements. The most innovative feature of iPhone 5s was a thin metal band surrounding the home button, a fingerprint sensor called Touch ID. Developers clambered to know about the API. A year on and iOS 8 introduces a new framework giving developers the ability to use the fingerprint sensor.

The Local Authentication framework provides methods to prompt a user to authenticate. You could use this as a login for your app or use it just to protect sensitive data within an app. In this tutorial, I will explain the options available to you, what data you can get from the device, and we’ll also build a sample app.

This tutorial requires Xcode 6 to create the project and you’ll need a device with Touch ID to test the sample app that we'll create.

1. Touch ID

Touch ID refers to the fingerprint sensor built into the home button of iPhone 5s. It was added to help encourage the use of passcodes by making it easier for users to authenticate. You can configure each device with a maximum of five fingerprints. Up to now, it has been used to unlock the device and to make purchases in the iTunes Store, App Store, and iBooks Store. Before we see how you might use it in your apps, here's a quick overview of the sensor itself.

The Touch ID sensor is able to scan your fingers at a resolution of 500 pixels per inch, allowing it to put each print into one of three categories, arch, whorl, or loop. The sensor is  designed to be truly convenient, you can scan your finger in any orientation and it'll determine a match with any existing fingerprint regardless of the original orientation.

Apple claim that the odds of a false positive for a given fingerprint is 1 in 50,000, which is much better than the odds of guessing a 4 digit pin code at 1 in 10,000. They don't mention that it's possible to fallback to using the pin number for times when you're not able to use your fingerprints, for example, when you're all wrinkly after swimming.

If you plan to use Touch ID, then it's important that you too consider scenarios where users can't use their finger as a means to authenticate. Because you're not able to verify against the device's pin code as Apple do, it may be a good idea to have users create a password within your app.

2. Security Considerations

The biggest concern with the fingerprint sensor is that users's privacy is fundamentally breached. If your password is revealed, you can change it to something new and a malicious person would no longer be able to use it to access your data. If your fingerprint, or Apple's mathematical representation of it, is exposed, you can't change it quite so easily.

The Local Authentication framework handles all of the heavy lifting of verifying users. When working with Touch ID, it's important to know that it reveals no details about the user and no data is transferred from the device. However, developers can use the framework to check if a user is allowed to use the app.

If you're familiar with the OAuth specification, you may see similarities in the way authentication is handled, you ask a third party to verify the identify of a user, if you trust the third party, you can use their response in place of requesting credentials directly from the user.

3. LAContext

The heart of the Local Authentication framework is the LAContext class. Developers can use an instance of LAContext to evaluate a security policy. At the time of writing, there is only one policy. It checks, using the Touch ID sensor, that the person authenticating is the device owner. In the future there may be other security policies. For example, Apple may introduce an unprivileged role that is only able to access certain resources.

If the framework is unable to authenticate, it throws an error. There are several reasons why a device isn't able to authenticate.

  • LAErrorTouchIDNotAvailable The device doesn't have a fingerprint sensor.
  • LAErrorPasscodeNotSet There is no passcode set on the device, which means that Touch ID is disabled.
  • LAErrorTouchIDNotEnrolled There is a passcode set but the device has not been configured with any fingerprints.

If an error is thrown with any of the above error codes, then you need to provide some other method for users to authenticate. At this point, you can't rely solely on Touch ID.

Let's create a sample app to learn how we can make use of the Local Authentication framework.

4. Project Setup

Step 1

Open Xcode and select New > Project... from the File menu. Choose Single View Application from the list of iOS Application templates and click Next.

Step 2

Enter a name for your project, I've called mine Auth. Enter your organization's name, company identifier, and class prefix. Choose iPhone from the Devices list, click Next, and choose a location to save the project.

Step 3

Click ViewController.h and define a new action, authenticateButtonTapped, which will trigger the authentication process. The interface of the ViewController class should look like this:

#import <UIKit/UIKit.h>

@interface ViewController : UIViewController

- (IBAction)authenticateButtonTapped:(id)sender;

@end

Step 4

Open Main.storyboard and drag a Button onto the view controller's view. Change the button label to read Authenticate.

Step 5

Right-click the button to show the Connections Inspector. Click the plus on the left of the Touch Up Inside event and select the view controller that contains the button. Another menu will appear in which you can select the action we declared a moment ago.

5. Authenticate a User

Step 1

Switch to ViewController.m to implement the authenticateButtonTapped method. At the top of the file add the following import statement for the Local Authentication framework.

 #import <LocalAuthentication/LocalAuthentication.h>

Step 2

In the authenticateButtonTapped method, we create a context and determine if the context can evaluate the LAPolicyDeviceOwnerAuthenticationWithBiometrics policy, otherwise show an error message.

- (IBAction)authenticateButtonTapped:(id)sender {
    LAContext *context = [[LAContext alloc] init];
    NSError *error = nil;
    if ([context canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&error]) {
        // Authenticate User
    } else {
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Error"
                                                        message:@"Your device cannot authenticate using TouchID."
                                                       delegate:nil
                                              cancelButtonTitle:@"Ok"
                                              otherButtonTitles:nil];
        [alert show];
    }
}

Step 3

If the LAContext object is able to authenticate using Touch ID, then we try to verify the user's identity. If no error is thrown, we tell the user if they are the owner of the device. The final implementation of the authenticateButtonTapped method is shown below.

- (void)authenicateButtonTapped:(id)sender {
   LAContext *context = [[LAContext alloc] init];

   NSError *error = nil;
   if ([context canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&error]) {
       [context evaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics
               localizedReason:@"Are you the device owner?"
                         reply:^(BOOL success, NSError *error) {

           if (error) {
               UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Error"
                                                               message:@"There was a problem verifying your identity."
                                                              delegate:nil
                                                     cancelButtonTitle:@"Ok"
                                                     otherButtonTitles:nil];
               [alert show];
               return;
           }

           if (success) {
               UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Success"
                                                               message:@"You are the device owner!"
                                                              delegate:nil
                                                     cancelButtonTitle:@"Ok"
                                                     otherButtonTitles:nil];
               [alert show];

           } else {
               UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Error"
                                                               message:@"You are not the device owner."
                                                              delegate:nil
                                                     cancelButtonTitle:@"Ok"
                                                     otherButtonTitles:nil];
               [alert show];
           }

       }];

   } else {

       UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Error"
                                                       message:@"Your device cannot authenticate using TouchID."
                                                      delegate:nil
                                             cancelButtonTitle:@"Ok"
                                             otherButtonTitles:nil];
       [alert show];

   }
}

6. Build and Run

Build and run the application on a physical device with a fingerprint sensor and tap the button to authenticate. As long as your device has Touch ID support, you should be prompted to authenticate. If you put your finger on the sensor, the app should tell you if you're the device owner or not.

Conclusion

In this tutorial, we looked at the Local Authentication framework introduced in iOS 8. By checking the identity of the authenticating user, the LAContext class allows users to identify themselves without providing sensitive data directly to the app.

2014-09-17T18:15:57.000Z2014-09-17T18:15:57.000ZJosh Sephton

Accessing Native Features with Xamarin.Forms

$
0
0

1. Setting the Stage

When it comes to writing mobile applications, it's important to integrate with the platform specific features that are available to you when it makes sense. For instance, if you were writing a navigation app, it would make sense for you to use the geolocation features of the device and platform. If you were creating an app to help people with a vision impairment, you would want to integrate with any text-to-speech features that were available as well.

It's the developers that take advantage of these features that set themselves and their apps apart from the rest. These simple things take just an ordinary app and make it great. But what happens when you want to take advantage of these features, but you have decided to adopt Xamarin.Forms as your cross-platform mechanism of choice? Do you have to give up hope on these features just because you decided that your app needs to be cross-platform and you want to be able to share as much logic and user interface code as possible? Absolutely not.

These types of questions inevitably cause some issues for developers that adopt newer technologies such as Xamarin.Forms. Prior to the release of Xamarin.Forms, when you were working directly with Xamarin.iOS, Xamarin.Android, and Windows Phone project templates, accessing these types of features was fairly straightforward. From the Xamarin perspective, if you could find sample C#—or even native language and SDK documentation—for a particular feature, you could simply map your code to the native concepts, because Xamarin did such a spectacular job of translating the same native concepts on those platforms into C# language constructs. Windows Phone features were even easier because there was no translation necessary. All you had to do was read the documentation.

Luckily for us as developers, Xamarin has put a lot of time and effort into designing a mechanism for us to access these same features even if we choose to use their Xamarin.Forms abstraction layer. This mechanism is know as the DependencyService.

2.DependencyService Overview

At first glance, a name like DependencyService may seem a little intimidating. It sounds like some fancy programming terminology that only the elite few understand. If you have ever worked with Dependency Injection (DI) or Inversion of Controller (IoC) containers, you should feel right at home with the DependencyService. If you haven't, I assure you that it is a very simple concept to understand once you break it down into its components.

What Is the DependencyService?

At it's most basic, DependencyService is a class. It's a class whose sole purpose of existence is to allow you to register any number of classes throughout your application. By register, I mean take any class you have and make it known to the service. Once the DependencyService knows about a class, it can go and retrieve an instance of that class whenever necessary. That is the other purpose of the DependencyService. If at any point in your application, you decide that you need an instance of a class that has been registered in the DependencyService, you can request or get an instance of it.

When you really get down into the nuts and bolts of the DependencyService, this is a very broad generalization. But from a developer's point of view, that's almost all you need to know. However, there is one other concept you need to be aware of when working with the DependencyService, interfaces. When it comes to the DependencyService and all of this registering and retrieving, you are typically doing that with respect to interfaces. This means that when you register a class, you are registering it as an implementation of a particular interface. And when you are retrieving a class, you are actually asking the DependencyService for an implementation of that interface. At this point, you don't really care what the implementation is, you just want a class that implements this interface.

How Does the DependencyService Work?

Now that you have a basic understanding at a conceptual level of what the DependencyService is, let's dig a little deeper and see how it actually works.

To use the DependencyService, you need three things:

  1. Interfaces: An interface is simply a construct that defines what members must be present within any class that chooses to implement, or agree, to this contract.
  2. Registration: Registration is merely the mechanism of letting the DependencyService know that a particular class wishes to be registered and be able to be retrieved later on.
  3. Location: This concept is often associated with a pattern in software development know as the Service Locator pattern. This simply means that you can go to a single place, the DependencyService, and request some functionality, a class, without having to directly instantiate a new instance.

Let's dig into each one of these concepts in a little more detail.

3. Interfaces

Interfaces are very common occurrences in most Object Oriented Programming (OOP) languages these days. Using an interface allows you to define a contract that contains a series of properties, methods, events, etc., that must be implemented by any class that agrees to that contract.

Here's a very simple example of an interface and a class that implements that interface.

public interface IFileGrabber
{
     string GetFileContents(string fileUri);
}

public SimpleGrabber : IFileGrabber
{
     public string GetFileContents(string fileUri)
     {
          return GetFileFromFileSystem(fileUri);
     }
}

This seems like a very simple example, but it serves the purpose quite well. The IFileGrabber interface defines a single method, GetFileContents. The SimpleGrabber class agrees to or implements the IFileGrabber interface, which means that it must contain an implementation for the one method.

Now, instead of having to implement other code in your application directly against a concrete class, SimpleGrabber, you can start to reference the IFileGrabber interface instead. Imagine you have another class in your application that looks like this:

public class DataRetriever
{
    private IFileGrabber _fileGrabber;
    public DataRetriever(IFileGrabber fileGrabber)
    {
        _fileGrabber = fileGrabber
    }

     public string GetFileContents(string fileUri)
     {
          return _fileGrabber.GetFileContents(fileUri);
     }
}

By using the IFileGrabber interface instead of a concrete class, you have the ability to create other mechanisms to retrieve files from different places and the DataRetriever class wouldn't care. Let's assume we have another class that looks like this:

public class NetworkGrabber : IFileGrabber
{
     public string GetFileContents(string fileUri)
     {
          return GetFileFromNetwork(fileUri);
     }
}

You now care less about how the class or the GetFileContents method is implemented, you just know that at least the members that are defined in the interface are present and that means you can continue to code away using just that interface as a reference. This is an incredibly important concept when it comes to the DependencyService.

4. Registration

In the context of the DependencyService, Xamarin has made the process of registering a class quite simple. Since you already have defined your interface and at least one class that implements it, you can register it in the DependencyService using a very simple assembly attribute.

Let's continue using the above example and register the SimpleGrabber class. The class definition would now looking something like this:

[assembly: Xamarin.Forms.Dependency(typeof(SimpleFileGrabber))]

// Any namespace declaration that may exist

public SimpleGrabber : IFileGrabber
{
     public string GetFileContents(string fileUri)
     {
          return GetFileFromFileSystem(fileUri);
     }
}

All you need to do is add the assembly reference above your class definition and outside of any namespace definition that may be contained within that file as well. By doing this simple task, you will have successfully registered the SimpleGrabber class as an implementation of the IFileGrabber interface.

When registering a class, that class must contain a parameterless constructor in order for the DependencyService to instantiate it. In my example above, I haven't defined a constructor so the compiler will, by default, create a parameterless constructor for me.

5. Location

The final piece of the puzzle is getting an instance of a registered class. This is actually the easiest part of the entire process. To retrieve an instance of a registered class, you simply use the DependencyService class and it's generic Get<>() method. Here's a simple example:

public class FileHelper
{
    public string GetFileContents(string fileUri)
    {
        return DependencyService.Get<IFileGrabber>().GetFileContents(fileUri);
    }
}

In this case, at runtime, you don't care where the DependencyService is getting the concrete class that implements the IFileGrabber interface. All you care about is that the class implements the IFileGrabber interface.

6. Using the DependencyService

Now that you have a conceptual understanding of what the DependencyService is and how to use it, let's create a simple application to put it to use.

For this example, I will be using Xamarin Studio 5, but feel free to use Visual Studio 2013 if you wish. Start by creating a new solution. In the New Solution dialog box, under the C# category on the left, select the Mobile Apps project family. On the right hand side, select either the Blank App (Xamarin.Forms Portable) or the Blank App (Xamarin.Forms Shared) project template. The code and the resulting application will be the same regardless of the template you choose.

In this example, I will be using the Portable Class Library (PCL) version of the template. Give a name to the project. I will be naming the solution and first project DependencyServiceSample. Then click the OK button.

This process will create three separate projects:

  • DependencyServiceSample - Shared library (PCL)
  • DependencyServiceSample.Android - Android project
  • DependencyServiceSample.iOS - iOS project

Xamarin Studio doesn't support creating Windows Phone projects. If you are using Visual Studio, this process will create four projects. It will create the above three projects as well as a Windows Phone project named DependencyServiceSample.WinPhone.

In the shared library (DependencyServiceSample), create a new interface file and name it ISampleInterface and give it the following implementation:

namespace DependencyServiceSample
{
    public interface ISampleInterface
	{
		string GetData();
	}
}

The is a standard looking interface file that defines a simple method named GetData that will return a string. Once again, the important point to understand is that from the perspective of the shared code file, it doesn't care what the implementation of this interface looks like. The only thing that matters is that whatever implementation is provided for this interface, it has a method named GetData that will return a string.

Next, we modify the App.cs file to use the DependencyService to get an instance of the ISampleInterface to use in your Xamarin.Forms app. Modify the  GetMainPage method to look like the following:

public static Page GetMainPage ()
    	{	
			return new ContentPage { 
				Content = new Label {
					Text = DependencyService.Get<ISampleInterface>().GetData(),
					VerticalOptions = LayoutOptions.CenterAndExpand,
					HorizontalOptions = LayoutOptions.CenterAndExpand,
				},
			};
		}

Notice that the only difference is that the Text property of the Label has been changed to the following line:

DependencyService.Get<ISampleInterface>().GetData()

This way, you are using the DependencyService class and the generic Get<>() method to retrieve whatever implementation of the ISampleInterface is implemented in the platform specific project that is currently running. Once that instance has been retrieved, you are calling the GetData method to get back a string and set the Text property of the Label.

The last step has two parts (three if you are using Visual Studio). At this point, you will need to implement the ISampleInterface interface in all of the platform specific projects in your solution.

Let's start in the DependencyServiceSample.Android application. All you need to do is create a new class file in the project and give it any name you like. I have named mine Sample_Android. Replace the default implementation with the following:

using System;
using DependencyServiceSample.Android;

[assembly: Xamarin.Forms.Dependency(typeof(Sample_Android))]

namespace DependencyServiceSample.Android
{
    public class Sample_Android : ISampleInterface
	{
		#region ISampleInterface implementation

		public string GetData ()
		{
			return "I came from the Android project!";
		}

		#endregion
	}
}

This is a simple class that implements the ISampleInterface interface and its implementation is to simply return a string stating that it's coming from the Android project. The only difference is the use of the assembly attribute at the top of the file that registers this class with the DependencyService so that it can be retrieved later.

Now, let's create another implementation of this interface in the iOS project. Create a new class in the iOS project, name it Sample_iOS, and replace the default implementation with the following:

using System;
using DependencyServiceSample.iOS;

[assembly: Xamarin.Forms.Dependency(typeof(Sample_iOS))]

namespace DependencyServiceSample.iOS
{
    public class Sample_iOS : ISampleInterface
	{
		#region ISampleInterface implementation

		public string GetData ()
		{
			return "I came from the iOS project!";
		}

		#endregion
	}
}

The implementation is exactly the same as the Android version, except that it returns a different string stating that it's coming from the iOS project this time. The final step is to run the application and see if you are getting the result you are expecting.

Here is the result of the iOS application running.

  

Here is the result of the Android application running.

As you can see, both applications run successfully. Not only do they run, but they are successfully running from a shared Xamarin.Forms project that is controlling the user interface. From that user interface code within Xamarin.Forms, you are now able to dip directly into the platform specific projects to access native code.

7. Where to Go From Here

Now that you have the skills to use the DependencyService to get access to native functionality from Xamarin.Forms, the sky's the limit. You can continue to write simple implementations as you have done in this tutorial or you can start to tap into more interesting features of the platforms.

One of the most interesting resources to take a look at for integrating into your DependencyService is the Recipes section of the Xamarin website. Here you'll find platform specific implementations of getting access to a number of features including:

  • Networking
  • Audio
  • Video
  • Geolocation
  • Accelerometers

All of these features are at your disposal when it comes to Xamarin.Forms applications. With the DependencyService, these features can be summoned at a moment's notice.

Conclusion

Now that you know and understand the DependencyService, you no longer have to feel intimidated when you need to access platform specific features from a Xamarin.Forms application. You now possess the tools that allow you to tap into those amazing native features of the devices that will ultimately allow you to differentiate your apps from the rest in the app stores.

Next Step: Watch the Course

If you'd like to learn more about Xamarin, then check out our course Building Multi-Platform Apps With C# in Xamarin

In the course, you will learn how to create a cross-platform application from a single code base that will run on three distinctly different platforms: iOS, Android, and Windows Phone 8. Think it can’t be done? In just a little while you will be doing it yourself. Let’s get to work.

You can take the straight away with a completely free 14 day trial of a Tuts+ subscription. Take a look at our subscription options to get started or, if you're just interested in this course, you can buy it individually for $15! Here's a preview to get you started:

2014-09-19T16:50:00.000Z2014-09-19T16:50:00.000ZDerek Jensen

Accessing Native Features with Xamarin.Forms

$
0
0
tag:code.tutsplus.com,2005:PostPresenter/cms-22103

1. Setting the Stage

When it comes to writing mobile applications, it's important to integrate with the platform specific features that are available to you when it makes sense. For instance, if you were writing a navigation app, it would make sense for you to use the geolocation features of the device and platform. If you were creating an app to help people with a vision impairment, you would want to integrate with any text-to-speech features that were available as well.

It's the developers that take advantage of these features that set themselves and their apps apart from the rest. These simple things take just an ordinary app and make it great. But what happens when you want to take advantage of these features, but you have decided to adopt Xamarin.Forms as your cross-platform mechanism of choice? Do you have to give up hope on these features just because you decided that your app needs to be cross-platform and you want to be able to share as much logic and user interface code as possible? Absolutely not.

These types of questions inevitably cause some issues for developers that adopt newer technologies such as Xamarin.Forms. Prior to the release of Xamarin.Forms, when you were working directly with Xamarin.iOS, Xamarin.Android, and Windows Phone project templates, accessing these types of features was fairly straightforward. From the Xamarin perspective, if you could find sample C#—or even native language and SDK documentation—for a particular feature, you could simply map your code to the native concepts, because Xamarin did such a spectacular job of translating the same native concepts on those platforms into C# language constructs. Windows Phone features were even easier because there was no translation necessary. All you had to do was read the documentation.

Luckily for us as developers, Xamarin has put a lot of time and effort into designing a mechanism for us to access these same features even if we choose to use their Xamarin.Forms abstraction layer. This mechanism is know as the DependencyService.

2.DependencyService Overview

At first glance, a name like DependencyService may seem a little intimidating. It sounds like some fancy programming terminology that only the elite few understand. If you have ever worked with Dependency Injection (DI) or Inversion of Controller (IoC) containers, you should feel right at home with the DependencyService. If you haven't, I assure you that it is a very simple concept to understand once you break it down into its components.

What Is the DependencyService?

At it's most basic, DependencyService is a class. It's a class whose sole purpose of existence is to allow you to register any number of classes throughout your application. By register, I mean take any class you have and make it known to the service. Once the DependencyService knows about a class, it can go and retrieve an instance of that class whenever necessary. That is the other purpose of the DependencyService. If at any point in your application, you decide that you need an instance of a class that has been registered in the DependencyService, you can request or get an instance of it.

When you really get down into the nuts and bolts of the DependencyService, this is a very broad generalization. But from a developer's point of view, that's almost all you need to know. However, there is one other concept you need to be aware of when working with the DependencyService, interfaces. When it comes to the DependencyService and all of this registering and retrieving, you are typically doing that with respect to interfaces. This means that when you register a class, you are registering it as an implementation of a particular interface. And when you are retrieving a class, you are actually asking the DependencyService for an implementation of that interface. At this point, you don't really care what the implementation is, you just want a class that implements this interface.

How Does the DependencyService Work?

Now that you have a basic understanding at a conceptual level of what the DependencyService is, let's dig a little deeper and see how it actually works.

To use the DependencyService, you need three things:

  1. Interfaces: An interface is simply a construct that defines what members must be present within any class that chooses to implement, or agree, to this contract.
  2. Registration: Registration is merely the mechanism of letting the DependencyService know that a particular class wishes to be registered and be able to be retrieved later on.
  3. Location: This concept is often associated with a pattern in software development know as the Service Locator pattern. This simply means that you can go to a single place, the DependencyService, and request some functionality, a class, without having to directly instantiate a new instance.

Let's dig into each one of these concepts in a little more detail.

3. Interfaces

Interfaces are very common occurrences in most Object Oriented Programming (OOP) languages these days. Using an interface allows you to define a contract that contains a series of properties, methods, events, etc., that must be implemented by any class that agrees to that contract.

Here's a very simple example of an interface and a class that implements that interface.

public interface IFileGrabber
{
     string GetFileContents(string fileUri);
}

public SimpleGrabber : IFileGrabber
{
     public string GetFileContents(string fileUri)
     {
          return GetFileFromFileSystem(fileUri);
     }
}

This seems like a very simple example, but it serves the purpose quite well. The IFileGrabber interface defines a single method, GetFileContents. The SimpleGrabber class agrees to or implements the IFileGrabber interface, which means that it must contain an implementation for the one method.

Now, instead of having to implement other code in your application directly against a concrete class, SimpleGrabber, you can start to reference the IFileGrabber interface instead. Imagine you have another class in your application that looks like this:

public class DataRetriever
{
    private IFileGrabber _fileGrabber;
    public DataRetriever(IFileGrabber fileGrabber)
    {
        _fileGrabber = fileGrabber
    }

     public string GetFileContents(string fileUri)
     {
          return _fileGrabber.GetFileContents(fileUri);
     }
}

By using the IFileGrabber interface instead of a concrete class, you have the ability to create other mechanisms to retrieve files from different places and the DataRetriever class wouldn't care. Let's assume we have another class that looks like this:

public class NetworkGrabber : IFileGrabber
{
     public string GetFileContents(string fileUri)
     {
          return GetFileFromNetwork(fileUri);
     }
}

You now care less about how the class or the GetFileContents method is implemented, you just know that at least the members that are defined in the interface are present and that means you can continue to code away using just that interface as a reference. This is an incredibly important concept when it comes to the DependencyService.

4. Registration

In the context of the DependencyService, Xamarin has made the process of registering a class quite simple. Since you already have defined your interface and at least one class that implements it, you can register it in the DependencyService using a very simple assembly attribute.

Let's continue using the above example and register the SimpleGrabber class. The class definition would now looking something like this:

[assembly: Xamarin.Forms.Dependency(typeof(SimpleFileGrabber))]

// Any namespace declaration that may exist

public SimpleGrabber : IFileGrabber
{
     public string GetFileContents(string fileUri)
     {
          return GetFileFromFileSystem(fileUri);
     }
}

All you need to do is add the assembly reference above your class definition and outside of any namespace definition that may be contained within that file as well. By doing this simple task, you will have successfully registered the SimpleGrabber class as an implementation of the IFileGrabber interface.

When registering a class, that class must contain a parameterless constructor in order for the DependencyService to instantiate it. In my example above, I haven't defined a constructor so the compiler will, by default, create a parameterless constructor for me.

5. Location

The final piece of the puzzle is getting an instance of a registered class. This is actually the easiest part of the entire process. To retrieve an instance of a registered class, you simply use the DependencyService class and it's generic Get<>() method. Here's a simple example:

public class FileHelper
{
    public string GetFileContents(string fileUri)
    {
        return DependencyService.Get<IFileGrabber>().GetFileContents(fileUri);
    }
}

In this case, at runtime, you don't care where the DependencyService is getting the concrete class that implements the IFileGrabber interface. All you care about is that the class implements the IFileGrabber interface.

6. Using the DependencyService

Now that you have a conceptual understanding of what the DependencyService is and how to use it, let's create a simple application to put it to use.

For this example, I will be using Xamarin Studio 5, but feel free to use Visual Studio 2013 if you wish. Start by creating a new solution. In the New Solution dialog box, under the C# category on the left, select the Mobile Apps project family. On the right hand side, select either the Blank App (Xamarin.Forms Portable) or the Blank App (Xamarin.Forms Shared) project template. The code and the resulting application will be the same regardless of the template you choose.

In this example, I will be using the Portable Class Library (PCL) version of the template. Give a name to the project. I will be naming the solution and first project DependencyServiceSample. Then click the OK button.

This process will create three separate projects:

  • DependencyServiceSample - Shared library (PCL)
  • DependencyServiceSample.Android - Android project
  • DependencyServiceSample.iOS - iOS project

Xamarin Studio doesn't support creating Windows Phone projects. If you are using Visual Studio, this process will create four projects. It will create the above three projects as well as a Windows Phone project named DependencyServiceSample.WinPhone.

In the shared library (DependencyServiceSample), create a new interface file and name it ISampleInterface and give it the following implementation:

namespace DependencyServiceSample
{
    public interface ISampleInterface
	{
		string GetData();
	}
}

The is a standard looking interface file that defines a simple method named GetData that will return a string. Once again, the important point to understand is that from the perspective of the shared code file, it doesn't care what the implementation of this interface looks like. The only thing that matters is that whatever implementation is provided for this interface, it has a method named GetData that will return a string.

Next, we modify the App.cs file to use the DependencyService to get an instance of the ISampleInterface to use in your Xamarin.Forms app. Modify the  GetMainPage method to look like the following:

public static Page GetMainPage ()
    	{	
			return new ContentPage { 
				Content = new Label {
					Text = DependencyService.Get<ISampleInterface>().GetData(),
					VerticalOptions = LayoutOptions.CenterAndExpand,
					HorizontalOptions = LayoutOptions.CenterAndExpand,
				},
			};
		}

Notice that the only difference is that the Text property of the Label has been changed to the following line:

DependencyService.Get<ISampleInterface>().GetData()

This way, you are using the DependencyService class and the generic Get<>() method to retrieve whatever implementation of the ISampleInterface is implemented in the platform specific project that is currently running. Once that instance has been retrieved, you are calling the GetData method to get back a string and set the Text property of the Label.

The last step has two parts (three if you are using Visual Studio). At this point, you will need to implement the ISampleInterface interface in all of the platform specific projects in your solution.

Let's start in the DependencyServiceSample.Android application. All you need to do is create a new class file in the project and give it any name you like. I have named mine Sample_Android. Replace the default implementation with the following:

using System;
using DependencyServiceSample.Android;

[assembly: Xamarin.Forms.Dependency(typeof(Sample_Android))]

namespace DependencyServiceSample.Android
{
    public class Sample_Android : ISampleInterface
	{
		#region ISampleInterface implementation

		public string GetData ()
		{
			return "I came from the Android project!";
		}

		#endregion
	}
}

This is a simple class that implements the ISampleInterface interface and its implementation is to simply return a string stating that it's coming from the Android project. The only difference is the use of the assembly attribute at the top of the file that registers this class with the DependencyService so that it can be retrieved later.

Now, let's create another implementation of this interface in the iOS project. Create a new class in the iOS project, name it Sample_iOS, and replace the default implementation with the following:

using System;
using DependencyServiceSample.iOS;

[assembly: Xamarin.Forms.Dependency(typeof(Sample_iOS))]

namespace DependencyServiceSample.iOS
{
    public class Sample_iOS : ISampleInterface
	{
		#region ISampleInterface implementation

		public string GetData ()
		{
			return "I came from the iOS project!";
		}

		#endregion
	}
}

The implementation is exactly the same as the Android version, except that it returns a different string stating that it's coming from the iOS project this time. The final step is to run the application and see if you are getting the result you are expecting.

Here is the result of the iOS application running.

  

Here is the result of the Android application running.

As you can see, both applications run successfully. Not only do they run, but they are successfully running from a shared Xamarin.Forms project that is controlling the user interface. From that user interface code within Xamarin.Forms, you are now able to dip directly into the platform specific projects to access native code.

7. Where to Go From Here

Now that you have the skills to use the DependencyService to get access to native functionality from Xamarin.Forms, the sky's the limit. You can continue to write simple implementations as you have done in this tutorial or you can start to tap into more interesting features of the platforms.

One of the most interesting resources to take a look at for integrating into your DependencyService is the Recipes section of the Xamarin website. Here you'll find platform specific implementations of getting access to a number of features including:

  • Networking
  • Audio
  • Video
  • Geolocation
  • Accelerometers

All of these features are at your disposal when it comes to Xamarin.Forms applications. With the DependencyService, these features can be summoned at a moment's notice.

Conclusion

Now that you know and understand the DependencyService, you no longer have to feel intimidated when you need to access platform specific features from a Xamarin.Forms application. You now possess the tools that allow you to tap into those amazing native features of the devices that will ultimately allow you to differentiate your apps from the rest in the app stores.

Next Step: Watch the Course

If you'd like to learn more about Xamarin, then check out our course Building Multi-Platform Apps With C# in Xamarin

In the course, you will learn how to create a cross-platform application from a single code base that will run on three distinctly different platforms: iOS, Android, and Windows Phone 8. Think it can’t be done? In just a little while you will be doing it yourself. Let’s get to work.

You can take the straight away with a completely free 14 day trial of a Tuts+ subscription. Take a look at our subscription options to get started or, if you're just interested in this course, you can buy it individually for $15! Here's a preview to get you started:

2014-09-19T16:50:00.000Z2014-09-19T16:50:00.000ZDerek Jensen

Windows Phone 8: Working With Media Content

$
0
0
tag:code.tutsplus.com,2005:PostPresenter/cms-20490

We can't imagine a mobile application without media content, such as images and sound. Media content is key for many applications. In this tutorial, I'll be showing you how to insert images and enable audio playback in a Windows Phone application. 

1. Working with Images

Virtually every Windows Phone application contains one or more images. Just imagine an application with no artwork, only text. That wouldn't be very pleasing in terms of user experience. It's therefore important that we learn how to add, use, and manipulate images in a Windows Phone application.

As in the previous tutorials, we start by creating a new Windows Phone project. To add an image to your application, toggle the Toolbox in Visual Studio and add an Image control to the design view. You can resize the Image control to fit your needs.

The next step is to populate the Image control with an actual image. We'll display an image that is part of every Windows Phone project. Open the Assets folder in the project's Solution Explorer and locate the Tile subfolder. It should contain a handful of images that we can use in our application. The image that we'll be using is named FlipCycleTileLarge.png.

We need to tell the Image control where it can find the image by specifying the relative path of the image. An Image control has a Source property for this purpose. The following code snippet shows how you can do this using XAML. This should feel familiar by now.

<Image Source="Assets/Tiles/FlipCycleTileLarge.png" 
    HorizontalAlignment="Left" 
    Height="197" Margin="0,10,0,0" 
    VerticalAlignment="Top" 
    Width="446"/>

After setting the Source property of the Image control, the design view should be updated, showing the image you've set. There are many more ways in which we can customize the image control, like giving it a border. Feel free to play with the Image control to find out what other properties you can set to customize it.

2. Working with Audio

You'll notice that playing audio is pretty easy as well. Before I show you how to play audio in your application, download the sample sound that that we'll be using from SoundBible.com and name it cat.mp3.

The goal is to play the sound when the user taps a button on the main page of our application. To add the sound to your Windows Phone project, right-click the Assets folder and select Add Existing Item from the the Add menu. Locate the sound file and add it to your project.

Add a Button control from the Toolbox to the design view, below the image we created earlier. Change the button's title by setting its Content property to "Play Sound“ and set the button's Name property to "PlaySoundButton". The Name property is particularly important as it will be available to us in the corresponding C# class.

Before we move on to the next step, add the following code snippet below the Button control in. As its name indicates, the code snippet describes a MediaElement. It points to the audio file we added to our project a bit earlier.

<MediaElement 
    AutoPlay="False" 
    Name="CatSound" 
    Source="Assets/cat.mp3" 
    HorizontalAlignment="Left" 
    Height="100" Margin="187,357,0,0" 
    VerticalAlignment="Top"
    Width="100"/>

You should end up with the following result.

<Button Name="PlaySoundButton" 
    Content="Play Sound" 
    HorizontalAlignment="Left" 
    Margin="106,263,0,0" 
    VerticalAlignment="Top" 
    Width="263"
    Height="94"/><MediaElement 
    AutoPlay="False" 
    Name="CatSound" 
    Source="Assets/cat.mp3" 
    HorizontalAlignment="Left" 
    Height="100" Margin="187,357,0,0" 
    VerticalAlignment="Top"
    Width="100"/>

It's time to implement the button's event handler. Double-click the button we just created to navigate to the C# class of the current page, MainPage.cs. You'll notice that Visual Studio already created an event handler for us, PlaySoundButton_Click. In the PlaySoundButton_Click method, we call Play on the CatSound object.

 private void PlaySoundButton_Click(object sender, RoutedEventArgs e) {
    CatSound.Play();
}

Remember that CatSound is the name we gave to the MediaElement a few moments ago. When we call the Play method on the MediaElement object, the latter looks at its Source property to find out what it needs to play.

That's how simple it is to play audio in a Windows Phone application. Run your application to try it out.

Conclusion

In this tutorial, you learned how to display images with the Image control and how to play audio using the MediaElement control. There's a lot more you can do with the MediaElement control, such as playing video. I encourage you to browse the documentation to learn more about these features.

2014-09-24T16:15:01.000Z2014-09-24T16:15:01.000ZSani Yusuf

Develop a 3D Skee Ball Game With Unity

$
0
0
Final product image
What You'll Be Creating

Introduction

In this tutorial, you'll learn how to create a mobile 3D game using C# and Unity. The objective of the game is to throw the ball into the holes using the touch screen.

You will learn about the following aspects of Unity game development in this tutorial:

  • importing 3D models
  • swipe gesture controls
  • class communication
  • physics forces
  • trigger colliders

1. Create a New Unity Project

Open Unity and select New Project from the File menu to open the new project dialog. Tell Unity where you want to save the project and set the Set up defaults for: menu to 3D.

2. Build Settings

In the next step, you're presented with Unity's user interface. Set the project up for mobile development by choosing Build Settings from the File menu and selecting your platform of choice.

3. Devices

The first thing we need to do after selecting the target platform is choosing the size of the artwork we'll be using in the game. This will help us select a proper size for the 3D textures and 2D GUI without making the artwork blurry or use textures that are too large for the target device. For example, the artwork needs to have a higher resolution if you're targeting an iPad with a retina display than a Lumia 520.

iOS

  • iPad without Retina: 1024px x 768px
  • iPad with Retina: 2048px x 1536px
  • 3.5" iPhone/iPod Touch without Retina: 320px x 480px
  • 3.5" iPhone/iPod with Retina: 960px x 640px
  • 4" iPhone/iPod Touch: 1136px x 640px

Android

Because Android is an open platform, there's a wide range of devices, screen resolutions, and pixel densities. A few of the more common ones are listed below.

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

Windows Phone & BlackBerry

  • Blackberry Z10: 720px x 1280px, 355 ppi
  • Nokia Lumia 520: 400px x 800px, 233 ppi
  • Nokia Lumia 1520: 1080px x 1920px, 367 ppi

Note that the code we'll write in this tutorial can be used to target any of the platforms.

4. Export Graphics

Depending on the devices you're targeting, you may need to convert the artwork to the recommended size and pixel density. You can do this in your favorite image editor. I've used the Adjust Size... function under the Tools menu in OS X's Preview application.

5. Unity User Interface

Before we get started, make sure the 2D button in the Scene panel is not highlighted. You can also modify the resolution that's being displayed in the Game panel.

You're then presented with the workspace panels, which we'll also use in this tutorial. Take a moment to look at the main interface panels, such as the Scene, Game, Hierarchy, Project, Assets, and Inspector. We'll use them frequently in this tutorial.

6. Game Interface

The user interface of the game is straightforward. The screenshot below gives you an idea of the artwork we'll be using and how the final user interface will end up looking. You can find the artwork and additional resources in the tutorial's source files on GitHub.

7. Programming Language

You can use one of three programming languages when using Unity, C#UnityScript, a variation of JavaScript, and Boo. Each programming language has its pros and cons, and it's up to you to decide which one you prefer. My personal preference goes to the C# programming language so that's the language I'll be using in this tutorial.

If you decide to use another programming language, then make sure to take a look at Unity's Script Reference for examples.

8. Sound Effects

I'll use a number of sounds to improve the audial experience of the game. The sound effects used in this tutorial were obtained from PlayOnLoop and Freesound.

9. 3D Models

To create the game, we first need to get a few 3D models. I recommend 3docean for high quality models and textures, but if you're testing or learning, then free models will work just as fine. The models in this tutorial were downloaded from SketchUp 3D Warehouse where you can find a wide variety of 3D models.

Because Unity doesn't recognize the SketchUp file format, we need to convert it to something Unity can import. We first need to download the free version of SketchUp, which is called SketchUp Make.

Open the 3D model in SketchUp Make, select Export > 3D Model from the File menu, and choose Collada (*.dae). Choose a name and location, and click Save. This will create a file and a folder for the 3D model. The file contains the data for the 3D object while the folder contains the model's textures. In the next step, we'll import the model into Unity.

10. Import Assets

Before we start coding, we need to add the assets to the Unity project. You can do this one of several ways:

  • select Import New Asset from the Assets menu
  • drag and drop the assets in the project window
  • add the items to the project's assets folder

After completing this step, you should see the assets in your project's Assets folder in the Project panel.

11. Setup Camera

Before we continue, let's position the main camera to create the view we want. Select the main camera from the Hierarchy panel and adjust the Transform values in the Inspector to match the ones shown below.

Don't worry if you don't see any changes. We haven't created anything for the camera to see yet.

12. Adding Light

For our objects to be visible in the 3D world, we need to add light to the scene. Select Create Other from the GameObject menu and select Directional Light. This will create an object that produces a beam of light. Change its Transform values as shown in the following screenshot to make it illuminate the area.

The light should be visible on the scene as shown in the following screenshot.

13. Add Alley Bowlers

The alley bowlers are the main components of the game's scene. The player will use the touch screen to throw a ball, aiming for one of the holes.

The model used in this tutorial was downloaded and imported using the method described in Step 9.

Even though we'll add three models to the scene, the play will only interact with the one in the center. Drag and drop an instance of the model on the Scene or Hierarchy panel and change its Transform values to the ones shown in the screenshot below.

Use the same method to add the other two instances or duplicate the first instance by pressing Command-D. Use the Transform Tools to position them as shown below.

14. Create Colliders

With the main alley in place, it's time to add colliders to the model to help us move the ball across its surface. Since this is a complex model with lots of groups and polygons, it would take us a long time identifying the various shapes and adding a collider to each of them. To make this step easier, we'll use a third-party script to automatically create a collider that fits our model.

The script will add a new menu item named Wizards to the Unity menu. Select the model to which you want to add the collider and select Add Mesh Colliders from the Wizards menu. This will bring up the following window.

Click Add Colliders in the bottom right to add colliders to the model. This will create a Mesh Collider for every group or object of the model. You can verify this by expanding the ballbowler model in the Hierarchy and selecting an item.

15. Spotlights

We've added a light source to our 3D world, but we need a bit more light to make the scene more interesting. We do this by adding a number of spotlights.

Select Create Other from the GameObject menu and select Spotlight. This will create an object that produces a beam of light directed to one spot. The first spotlight we add needs to illuminate the holes. Change its Transform values as shown in the following screenshot.

Add a second spotlight using the following transform values.

16. Ball

The ball is the most important component of the game. The player will use the touch screen to try and get the ball in one of the holes.

The ball is going to be a simple Sphere primitive. Select Create Other > Sphere from the GameObject menu to create the primitive and modify the Transform values in the Inspector as shown below.

We'll convert the ball to a Prefab later as it will help us create instances of it in code. But first, let's add a RigidBody to it.

17. Ball RigidBody

To detect a collision with the ball, we need to attach a RigidBody to it. To add one, select Add Component from the Inspector panel, followed by Physics > RigidBody. You can leave the settings at their defaults.

18. Ball Sensors

We need to detect when the ball falls into a hole. We'll use Trigger Colliders for this purpose. A trigger collider is a physics object that detects a collision with another object without reacting physically. This will help us detect when the ball enters the hole without making it bounce back.

Since we don't need an actual model or 2D graphic to do this, we'll create an Empty GameObject. Select GameObject > Create Empty from the menu bar to create it. Click the Add Component button in the Inspector and choose Physics > Box Collider.

This will add a box collider to the game object. Repeat this process for every hole and make sure to check the Trigger checkbox.

Position the colliders as shown in the screenshot below.

19. Scoreboard

To display the game's scoreboard, we'll use Unity's GUI Textures. By default, images imported to the Assets folder are converted to Texture instances that can be applied to 3D objects. We need to change these Texture instances to GUI Texture instances for the images we want to use in the game's user interface.

Select the image you want to convert in the Assets panel and open the Inspector. Select GUI from the Texture Type menu.

You can now drag and drop the image to the Scene. The image will always appear in front of every object on the stage and will be treated as a 2D element.

20. Scoreboard Text

Inside the scoreboard GUI element, we'll display numbers indicating the player's score and the number of balls the player has left.

Select Create Other > GUI Text from the GameObject menu to create a text object, place it at the center of the GUI element, and change the text in the Hierarchy panel to 00. Follow the same process for the balls text to complete the scoreboard.

21. Adding Scripts

It's time to write some code. With the user interface in place, we can start writing the necessary code to add interaction to the game. We do this by means of scripts, which can be attached to game objects. Follow the next steps to learn how to add interaction to the level we've just created.

22. ThrowBall Class

Step 1: Declaring Variables

We'll start by creating the class that handles most of the game mechanics. Select the main camera, click the Add Component button in the Inspector panel, and choose New Script. Name the script ThrowBall and don't forget to change the language to C#. Open the newly created file and add the following code snippet.

using UnityEngine;
using System.Collections;

public class ThrowBall : MonoBehaviour
{
    private Vector3 throwSpeed = new Vector3(0, 0, 1100);
    public GameObject ballReference;
    private Vector2 startPos;
    private Vector2 endPos;
    private Vector2 minDistance = new Vector2(0, 100);
    private Vector3 ballPos = new Vector3(0, 0.38f, -11.41f);
    public bool ballOnStage = false;
    public int ballsLeft = 5;
    public GUIText ballsTextReference;
    public AudioClip throwSound;

We start by creating a number of variables that we'll use in the game. Let's take a look at each one.

  • throwSpeed: the initial velocity of the ball when placed on the alley
  • ballReference: a reference to the ball prefab, set in the inspector
  • startPos: start position of the first touch, used to detect a swipe gesture
  • endPos: end position of the touch
  • minDistance: minimum movement needed for the finger to be considered a swipe
  • ballPos: initial ball position
  • ballOnStage: true when a ball is currently on the alley, to prevent multiple shots at the same time
  • ballsLeft: the number of remaining balls
  • ballsTextReference: reference to the balls textfield, set in the inspector
  • throwSound: reference to the sound played when the ball is thrown, set in the inspector

Step 2: Detecting Touches

The following code snippet shows the beginning of the Update method. This method detects if the user is touching the screen.

void Update()
{
    if(Input.touchCount > 0)
    {
        Touch touch = Input.GetTouch(0);

We check the touchCount property of the Input class to get the current number of touches on the screen. If touchCount is greater than 0, we keep a reference to the first Touch object. We'll use this object later.

Step 3: Detecting a Swipe

With a reference to the Touch object, we have access to its phase property, which helps us determine if the touch has started, moved, or ended.

Because we need a starting point to detect a swipe gesture, we need access to the starting point of the Touch object, which we have access to when the Touch object's phase is equal to TouchPhase.Began. The position of the Touch object is stored in its position property.

We have access to the endpoint of the gesture by accessing the Touch object's position property when its phase property is equal to TouchPhase.Ended.

if(touch.phase == TouchPhase.Began)
{
    startPos = touch.position;
}
if(touch.phase == TouchPhase.Ended)
{
    endPos = touch.position;
}

/* Compare positions */

if(endPos.y - startPos.y >= minDistance.y && !ballOnStage && ballsLeft > 0)
{

Now that we have the coordinates of the start and endpoint of the touch, we can calculate the distance and check whether it's a valid swipe gesture by comparing it with the value stored in the minDistance object.

We also inspect the value of ballOnStage to check if a ball is already on the scene and we make sure that the player has enough balls left to continue playing. The number of balls left is stored in the ballsLeft variable.

Step 4: Detecting the Screen Zone

Screen zones are created to calculate where the horizontal position of the ball is going to be when the ball is created. We do this to have control over the ball's position and it tells us where the ball is going to end and prevent throwing it out of bounds. We divide the screen in three parts as you can see below.


The math we use is quite simple as you can see in the code block below. We divide the screen in three equal parts and check which part contains the user's touch.

/* Divide screen in 3 parts */

/* Left */
if(touch.position.x >= 0 && touch.position.x <= Screen.width / 3)
{
    ballPos.x = Random.Range(-0.87f, -0.35f);
}
/* Center */
else if(touch.position.x > Screen.width / 3 && touch.position.x <= (Screen.width / 3) * 2)
{
    ballPos.x = Random.Range(-0.35f, 0.22f);
}
/* Right */
else if(touch.position.x > (Screen.width / 3) * 2 && touch.position.x <= Screen.width)
{
    ballPos.x = Random.Range(0.22f, 0.36f);
}

After detecting the correct screen zone, we calculate a random position between the start and end of the zone and assign that position to the ballPos variable.

Step 5: Throwing the Ball

After determining the starting position of the ball, we create a new GameObject instance using the Instantiate method, passing in the ballReference and ballPos variables.

GameObject ball = Instantiate(ballReference, ballPos, transform.rotation) as GameObject;
ball.rigidbody.AddForce(throwSpeed);

With the ball on the scene, we add a force to make it move through the correct alley. We do this by invoking the AddForce method on the ball's rigidbody property, passing in the throwSpeed variable we declared earlier.

Step 6: Playing a Sound Effect

We play a sound effect when the ball is thrown in the alley. The next line of code takes care of that. For this tot work, remember to set the throwSound variable in the Inspector.

AudioSource.PlayClipAtPoint(throwSound, transform.position);

Step 7: Resetting the Swipe Variables

After throwing the ball, we need to reset the variables that detect the player's touches. Not doing this would result in multiple swipes being detected. We also set the ballOnStage variable to true, preventing that another ball is thrown at the same time.

endPos = new Vector2(0, 0);
startPos = new Vector2(0, 0);
ballOnStage = true;

This completes the ThrowBall class. The implementation of the class should look like th one shown below.

using UnityEngine;
using System.Collections;

public class ThrowBall : MonoBehaviour
{
    private Vector3 throwSpeed = new Vector3(0, 0, 1100);
    public GameObject ballReference;
    private Vector2 startPos;
    private Vector2 endPos;
    private Vector2 minDistance = new Vector2(0, 100);
    private Vector3 ballPos = new Vector3(0, 0.38f, -11.41f);
    public bool ballOnStage = false;
    public int ballsLeft = 5;
    public GUIText ballsTextReference;
    public AudioClip throwSound;

    void Update()
    {
        if(Input.touchCount > 0)
        {
            Touch touch = Input.GetTouch(0);

            if(touch.phase == TouchPhase.Began)
            {
                startPos = touch.position;
            }
            if(touch.phase == TouchPhase.Ended)
            {
                endPos = touch.position;
            }

            /* Compare positions */

            if(endPos.y - startPos.y >= minDistance.y && !ballOnStage && ballsLeft > 0)
            {
                /* Divide screen in 3 parts */
                /* Left */
                if(touch.position.x >= 0 && touch.position.x <= Screen.width / 3)
                {
                    ballPos.x = Random.Range(-0.87f, -0.35f);
                }
                /* Center */
                else if(touch.position.x > Screen.width / 3 && touch.position.x <= (Screen.width / 3) * 2)
                {
                    ballPos.x = Random.Range(-0.35f, 0.22f);
                }
                /* Right */
                else if(touch.position.x > (Screen.width / 3) * 2 && touch.position.x <= Screen.width)
                {
                    ballPos.x = Random.Range(0.22f, 0.36f);
                }

                GameObject ball = Instantiate(ballReference, ballPos, transform.rotation) as GameObject;
                ball.rigidbody.AddForce(throwSpeed);

                AudioSource.PlayClipAtPoint(throwSound, transform.position);

                endPos = new Vector2(0, 0);
                startPos = new Vector2(0, 0);
                ballOnStage = true;
            }
        }
    }
}

23. BallSensor Class

The following script contains the implementation of the BallSensor class and is attached to the ball sensors, handling any collisions with the ball sensors.

Step 1: Declaring Variables

We start by declaring a variable named sensorValue, which stores the number of points the ball sensor will add to the score. Because the ball sensors are all the same prefab, we declare this variable as public. This will allow us to set this value in the editor using the Inspector.

using UnityEngine;
using System.Collections;

public class BallSensor : MonoBehaviour
{
    public int sensorValue = 0;
    public GUIText scoreReference;
    public GameObject alertReference;

The other two variables store references to the score and alert game objects, which we also set in Unity's InspectorThese references will be used to increase the score and display the alert when the game ends.

Step 2: Destroying the Ball

The OnTriggerEnter method detects when a collision has occurred and accepts the Collider object the sensor is colliding with, the ball in this case. When a collision is detected, the ball is destroyed to prevent it from bouncing and potentially falling in another hole.

void OnTriggerEnter(Collider other)
{
    Destroy(other.gameObject);

Step 3: Enabling Throw

After destroying the ball, we are sure that it isn't on the alley anymore. This means we can throw another ball without causing an unwanted behavior. The following line of code communicates with the ThrowBall class and gets the ballOnStage variable, setting it to false.

Camera.main.GetComponent<ThrowBall>().ballOnStage = false;

Let's take a closer look at how we access a variable declared in another class. As you can tell by now, one way to access a variable or object declared outside of the current class is to set a reference variable using public or [SerializeField], and then use the Inspector to give it a value.

The public keyword plays an important role in this. Using it makes the variable not only accessible from the Inspector, but also through code. To do this, we first need access to the GameObject that has the Script Component attached to it, which is the Main Camera in this case.

There is only one camera in this game, which makes things easier. We can get a reference to the main camera through Camera.main. Using GetComponent we get the script attached to the camera, using the name of the class. We then have access to the public variable named ballOnStage.

Step 4: Changing the Score

The following code block updates the score, using the reference we declared earlier.

scoreReference.text = (int.Parse(scoreReference.text) + sensorValue).ToString();

We convert the value stored in scoreReference to an integer and add it to the value stored in sensorValue. We convert the result to a string and assign it to the text property of scoreReference.

Step 5: Updating the Remaining Balls

In this step, we decrease the number of remaining balls. We use the method described in Step 3 to access the ballsLeft and ballsTextReference variables of the ThrowBall class.

Camera.main.GetComponent<ThrowBall>().ballsLeft--;
Camera.main.GetComponent<ThrowBall>().ballsTextReference.text = Camera.main.GetComponent<ThrowBall>().ballsLeft.ToString();

We decrement the value stored in ballsLeft and update the text property of ballsTextReference.

Step 6: Checking for Game Over

The game is over when the player runs out of available shots. The next lines of code check if the ballsLeft variable is equal to 0 and create an alert if true. We then call the Invoke method to invoke the Reload method, which restarts the game by reloading the current scene.

The second parameter of the Invoke method defines the delay with which the Reload method will be invoked. We do this to give the player some time before we start a new game.

    if (Camera.main.GetComponent<ThrowBall>().ballsLeft == 0)
    {
        Instantiate(alertReference, new Vector3(0.5f, 0.5f, 0), transform.rotation);
        Invoke("Reload", 3);
    }
}

Step 7: Reloading the Game

This is the last part of the BallSensor class. In the Reload method, we call LoadLevel on the Application class and reload the current level, resetting every object and variable to its initial state.

    void Reload()
    {
        Application.LoadLevel(Application.loadedLevel);
    }
}

This is what the class looks like when finished.

using UnityEngine;
using System.Collections;

public class BallSensor : MonoBehaviour
{
    public int sensorValue = 0;
    public GUIText scoreReference;
    public GameObject alertReference;

    void OnTriggerEnter(Collider other)
    {
        Destroy(other.gameObject);
        Camera.main.GetComponent<ThrowBall>().ballOnStage = false;
        scoreReference.text = (int.Parse(scoreReference.text) + sensorValue).ToString();

        Camera.main.GetComponent<ThrowBall>().ballsLeft--;
        Camera.main.GetComponent<ThrowBall>().ballsTextReference.text = Camera.main.GetComponent<ThrowBall>().ballsLeft.ToString();

        if (Camera.main.GetComponent<ThrowBall>().ballsLeft == 0)
        {
            Instantiate(alertReference, new Vector3(0.5f, 0.5f, 0), transform.rotation);
            Invoke("Reload", 3);
        }
    }

    void Reload()
    {
        Application.LoadLevel(Application.loadedLevel);
    }
}

24. Testing

It's time to test the game. Press Command-P to play the game in Unity. If everything works as expected, then you're ready for the final steps.

25. Player Settings

When you're happy with your game, it's time to select Build Settings from the File menu and click the Player Settings button. This should bring up the Player Settings in the Inspector panel where you can set the parameters for your application.

These settings are application specific data that includes the creator or company, app resolution and display mode, rendering mode (CPU, GPU), device OS compatibility, etc. Configure the settings according to the devices you're targeting and the store or market where you plan to publish the app.

26. Icons and Splash Images

Using the graphics you created earlier, you can now create a nice icon and a splash image for your game. Unity shows you the required sizes, which depend on the platform you're building for.

27. Build and Play


Once your project is properly configured, it's time to revisit the Build Settings and click the Build Button. That's all it takes to build your game for testing and/or distribution.

Conclusion

In this tutorial, we've learned how to use physics forces, swipe gestures, class communication, and other aspects of game development in Unity. I encourage you to experiment with the result and customize the game to make it your own. I hope you liked this tutorial and found it helpful.

2014-09-26T16:45:19.000Z2014-09-26T16:45:19.000ZCarlos Yanez

Develop a 3D Skee Ball Game With Unity

$
0
0
tag:code.tutsplus.com,2005:PostPresenter/cms-21891
Final product image
What You'll Be Creating

Introduction

In this tutorial, you'll learn how to create a mobile 3D game using C# and Unity. The objective of the game is to throw the ball into the holes using the touch screen.

You will learn about the following aspects of Unity game development in this tutorial:

  • importing 3D models
  • swipe gesture controls
  • class communication
  • physics forces
  • trigger colliders

1. Create a New Unity Project

Open Unity and select New Project from the File menu to open the new project dialog. Tell Unity where you want to save the project and set the Set up defaults for: menu to 3D.

2. Build Settings

In the next step, you're presented with Unity's user interface. Set the project up for mobile development by choosing Build Settings from the File menu and selecting your platform of choice.

3. Devices

The first thing we need to do after selecting the target platform is choosing the size of the artwork we'll be using in the game. This will help us select a proper size for the 3D textures and 2D GUI without making the artwork blurry or use textures that are too large for the target device. For example, the artwork needs to have a higher resolution if you're targeting an iPad with a retina display than a Lumia 520.

iOS

  • iPad without Retina: 1024px x 768px
  • iPad with Retina: 2048px x 1536px
  • 3.5" iPhone/iPod Touch without Retina: 320px x 480px
  • 3.5" iPhone/iPod with Retina: 960px x 640px
  • 4" iPhone/iPod Touch: 1136px x 640px

Android

Because Android is an open platform, there's a wide range of devices, screen resolutions, and pixel densities. A few of the more common ones are listed below.

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

Windows Phone & BlackBerry

  • Blackberry Z10: 720px x 1280px, 355 ppi
  • Nokia Lumia 520: 400px x 800px, 233 ppi
  • Nokia Lumia 1520: 1080px x 1920px, 367 ppi

Note that the code we'll write in this tutorial can be used to target any of the platforms.

4. Export Graphics

Depending on the devices you're targeting, you may need to convert the artwork to the recommended size and pixel density. You can do this in your favorite image editor. I've used the Adjust Size... function under the Tools menu in OS X's Preview application.

5. Unity User Interface

Before we get started, make sure the 2D button in the Scene panel is not highlighted. You can also modify the resolution that's being displayed in the Game panel.

You're then presented with the workspace panels, which we'll also use in this tutorial. Take a moment to look at the main interface panels, such as the Scene, Game, Hierarchy, Project, Assets, and Inspector. We'll use them frequently in this tutorial.

6. Game Interface

The user interface of the game is straightforward. The screenshot below gives you an idea of the artwork we'll be using and how the final user interface will end up looking. You can find the artwork and additional resources in the tutorial's source files on GitHub.

7. Programming Language

You can use one of three programming languages when using Unity, C#UnityScript, a variation of JavaScript, and Boo. Each programming language has its pros and cons, and it's up to you to decide which one you prefer. My personal preference goes to the C# programming language so that's the language I'll be using in this tutorial.

If you decide to use another programming language, then make sure to take a look at Unity's Script Reference for examples.

8. Sound Effects

I'll use a number of sounds to improve the audial experience of the game. The sound effects used in this tutorial were obtained from PlayOnLoop and Freesound.

9. 3D Models

To create the game, we first need to get a few 3D models. I recommend 3docean for high quality models and textures, but if you're testing or learning, then free models will work just as fine. The models in this tutorial were downloaded from SketchUp 3D Warehouse where you can find a wide variety of 3D models.

Because Unity doesn't recognize the SketchUp file format, we need to convert it to something Unity can import. We first need to download the free version of SketchUp, which is called SketchUp Make.

Open the 3D model in SketchUp Make, select Export > 3D Model from the File menu, and choose Collada (*.dae). Choose a name and location, and click Save. This will create a file and a folder for the 3D model. The file contains the data for the 3D object while the folder contains the model's textures. In the next step, we'll import the model into Unity.

10. Import Assets

Before we start coding, we need to add the assets to the Unity project. You can do this one of several ways:

  • select Import New Asset from the Assets menu
  • drag and drop the assets in the project window
  • add the items to the project's assets folder

After completing this step, you should see the assets in your project's Assets folder in the Project panel.

11. Setup Camera

Before we continue, let's position the main camera to create the view we want. Select the main camera from the Hierarchy panel and adjust the Transform values in the Inspector to match the ones shown below.

Don't worry if you don't see any changes. We haven't created anything for the camera to see yet.

12. Adding Light

For our objects to be visible in the 3D world, we need to add light to the scene. Select Create Other from the GameObject menu and select Directional Light. This will create an object that produces a beam of light. Change its Transform values as shown in the following screenshot to make it illuminate the area.

The light should be visible on the scene as shown in the following screenshot.

13. Add Alley Bowlers

The alley bowlers are the main components of the game's scene. The player will use the touch screen to throw a ball, aiming for one of the holes.

The model used in this tutorial was downloaded and imported using the method described in Step 9.

Even though we'll add three models to the scene, the play will only interact with the one in the center. Drag and drop an instance of the model on the Scene or Hierarchy panel and change its Transform values to the ones shown in the screenshot below.

Use the same method to add the other two instances or duplicate the first instance by pressing Command-D. Use the Transform Tools to position them as shown below.

14. Create Colliders

With the main alley in place, it's time to add colliders to the model to help us move the ball across its surface. Since this is a complex model with lots of groups and polygons, it would take us a long time identifying the various shapes and adding a collider to each of them. To make this step easier, we'll use a third-party script to automatically create a collider that fits our model.

The script will add a new menu item named Wizards to the Unity menu. Select the model to which you want to add the collider and select Add Mesh Colliders from the Wizards menu. This will bring up the following window.

Click Add Colliders in the bottom right to add colliders to the model. This will create a Mesh Collider for every group or object of the model. You can verify this by expanding the ballbowler model in the Hierarchy and selecting an item.

15. Spotlights

We've added a light source to our 3D world, but we need a bit more light to make the scene more interesting. We do this by adding a number of spotlights.

Select Create Other from the GameObject menu and select Spotlight. This will create an object that produces a beam of light directed to one spot. The first spotlight we add needs to illuminate the holes. Change its Transform values as shown in the following screenshot.

Add a second spotlight using the following transform values.

16. Ball

The ball is the most important component of the game. The player will use the touch screen to try and get the ball in one of the holes.

The ball is going to be a simple Sphere primitive. Select Create Other > Sphere from the GameObject menu to create the primitive and modify the Transform values in the Inspector as shown below.

We'll convert the ball to a Prefab later as it will help us create instances of it in code. But first, let's add a RigidBody to it.

17. Ball RigidBody

To detect a collision with the ball, we need to attach a RigidBody to it. To add one, select Add Component from the Inspector panel, followed by Physics > RigidBody. You can leave the settings at their defaults.

18. Ball Sensors

We need to detect when the ball falls into a hole. We'll use Trigger Colliders for this purpose. A trigger collider is a physics object that detects a collision with another object without reacting physically. This will help us detect when the ball enters the hole without making it bounce back.

Since we don't need an actual model or 2D graphic to do this, we'll create an Empty GameObject. Select GameObject > Create Empty from the menu bar to create it. Click the Add Component button in the Inspector and choose Physics > Box Collider.

This will add a box collider to the game object. Repeat this process for every hole and make sure to check the Trigger checkbox.

Position the colliders as shown in the screenshot below.

19. Scoreboard

To display the game's scoreboard, we'll use Unity's GUI Textures. By default, images imported to the Assets folder are converted to Texture instances that can be applied to 3D objects. We need to change these Texture instances to GUI Texture instances for the images we want to use in the game's user interface.

Select the image you want to convert in the Assets panel and open the Inspector. Select GUI from the Texture Type menu.

You can now drag and drop the image to the Scene. The image will always appear in front of every object on the stage and will be treated as a 2D element.

20. Scoreboard Text

Inside the scoreboard GUI element, we'll display numbers indicating the player's score and the number of balls the player has left.

Select Create Other > GUI Text from the GameObject menu to create a text object, place it at the center of the GUI element, and change the text in the Hierarchy panel to 00. Follow the same process for the balls text to complete the scoreboard.

21. Adding Scripts

It's time to write some code. With the user interface in place, we can start writing the necessary code to add interaction to the game. We do this by means of scripts, which can be attached to game objects. Follow the next steps to learn how to add interaction to the level we've just created.

22. ThrowBall Class

Step 1: Declaring Variables

We'll start by creating the class that handles most of the game mechanics. Select the main camera, click the Add Component button in the Inspector panel, and choose New Script. Name the script ThrowBall and don't forget to change the language to C#. Open the newly created file and add the following code snippet.

using UnityEngine;
using System.Collections;

public class ThrowBall : MonoBehaviour
{
    private Vector3 throwSpeed = new Vector3(0, 0, 1100);
    public GameObject ballReference;
    private Vector2 startPos;
    private Vector2 endPos;
    private Vector2 minDistance = new Vector2(0, 100);
    private Vector3 ballPos = new Vector3(0, 0.38f, -11.41f);
    public bool ballOnStage = false;
    public int ballsLeft = 5;
    public GUIText ballsTextReference;
    public AudioClip throwSound;

We start by creating a number of variables that we'll use in the game. Let's take a look at each one.

  • throwSpeed: the initial velocity of the ball when placed on the alley
  • ballReference: a reference to the ball prefab, set in the inspector
  • startPos: start position of the first touch, used to detect a swipe gesture
  • endPos: end position of the touch
  • minDistance: minimum movement needed for the finger to be considered a swipe
  • ballPos: initial ball position
  • ballOnStage: true when a ball is currently on the alley, to prevent multiple shots at the same time
  • ballsLeft: the number of remaining balls
  • ballsTextReference: reference to the balls textfield, set in the inspector
  • throwSound: reference to the sound played when the ball is thrown, set in the inspector

Step 2: Detecting Touches

The following code snippet shows the beginning of the Update method. This method detects if the user is touching the screen.

void Update()
{
    if(Input.touchCount > 0)
    {
        Touch touch = Input.GetTouch(0);

We check the touchCount property of the Input class to get the current number of touches on the screen. If touchCount is greater than 0, we keep a reference to the first Touch object. We'll use this object later.

Step 3: Detecting a Swipe

With a reference to the Touch object, we have access to its phase property, which helps us determine if the touch has started, moved, or ended.

Because we need a starting point to detect a swipe gesture, we need access to the starting point of the Touch object, which we have access to when the Touch object's phase is equal to TouchPhase.Began. The position of the Touch object is stored in its position property.

We have access to the endpoint of the gesture by accessing the Touch object's position property when its phase property is equal to TouchPhase.Ended.

if(touch.phase == TouchPhase.Began)
{
    startPos = touch.position;
}
if(touch.phase == TouchPhase.Ended)
{
    endPos = touch.position;
}

/* Compare positions */

if(endPos.y - startPos.y >= minDistance.y && !ballOnStage && ballsLeft > 0)
{

Now that we have the coordinates of the start and endpoint of the touch, we can calculate the distance and check whether it's a valid swipe gesture by comparing it with the value stored in the minDistance object.

We also inspect the value of ballOnStage to check if a ball is already on the scene and we make sure that the player has enough balls left to continue playing. The number of balls left is stored in the ballsLeft variable.

Step 4: Detecting the Screen Zone

Screen zones are created to calculate where the horizontal position of the ball is going to be when the ball is created. We do this to have control over the ball's position and it tells us where the ball is going to end and prevent throwing it out of bounds. We divide the screen in three parts as you can see below.


The math we use is quite simple as you can see in the code block below. We divide the screen in three equal parts and check which part contains the user's touch.

/* Divide screen in 3 parts */

/* Left */
if(touch.position.x >= 0 && touch.position.x <= Screen.width / 3)
{
    ballPos.x = Random.Range(-0.87f, -0.35f);
}
/* Center */
else if(touch.position.x > Screen.width / 3 && touch.position.x <= (Screen.width / 3) * 2)
{
    ballPos.x = Random.Range(-0.35f, 0.22f);
}
/* Right */
else if(touch.position.x > (Screen.width / 3) * 2 && touch.position.x <= Screen.width)
{
    ballPos.x = Random.Range(0.22f, 0.36f);
}

After detecting the correct screen zone, we calculate a random position between the start and end of the zone and assign that position to the ballPos variable.

Step 5: Throwing the Ball

After determining the starting position of the ball, we create a new GameObject instance using the Instantiate method, passing in the ballReference and ballPos variables.

GameObject ball = Instantiate(ballReference, ballPos, transform.rotation) as GameObject;
ball.rigidbody.AddForce(throwSpeed);

With the ball on the scene, we add a force to make it move through the correct alley. We do this by invoking the AddForce method on the ball's rigidbody property, passing in the throwSpeed variable we declared earlier.

Step 6: Playing a Sound Effect

We play a sound effect when the ball is thrown in the alley. The next line of code takes care of that. For this tot work, remember to set the throwSound variable in the Inspector.

AudioSource.PlayClipAtPoint(throwSound, transform.position);

Step 7: Resetting the Swipe Variables

After throwing the ball, we need to reset the variables that detect the player's touches. Not doing this would result in multiple swipes being detected. We also set the ballOnStage variable to true, preventing that another ball is thrown at the same time.

endPos = new Vector2(0, 0);
startPos = new Vector2(0, 0);
ballOnStage = true;

This completes the ThrowBall class. The implementation of the class should look like th one shown below.

using UnityEngine;
using System.Collections;

public class ThrowBall : MonoBehaviour
{
    private Vector3 throwSpeed = new Vector3(0, 0, 1100);
    public GameObject ballReference;
    private Vector2 startPos;
    private Vector2 endPos;
    private Vector2 minDistance = new Vector2(0, 100);
    private Vector3 ballPos = new Vector3(0, 0.38f, -11.41f);
    public bool ballOnStage = false;
    public int ballsLeft = 5;
    public GUIText ballsTextReference;
    public AudioClip throwSound;

    void Update()
    {
        if(Input.touchCount > 0)
        {
            Touch touch = Input.GetTouch(0);

            if(touch.phase == TouchPhase.Began)
            {
                startPos = touch.position;
            }
            if(touch.phase == TouchPhase.Ended)
            {
                endPos = touch.position;
            }

            /* Compare positions */

            if(endPos.y - startPos.y >= minDistance.y && !ballOnStage && ballsLeft > 0)
            {
                /* Divide screen in 3 parts */
                /* Left */
                if(touch.position.x >= 0 && touch.position.x <= Screen.width / 3)
                {
                    ballPos.x = Random.Range(-0.87f, -0.35f);
                }
                /* Center */
                else if(touch.position.x > Screen.width / 3 && touch.position.x <= (Screen.width / 3) * 2)
                {
                    ballPos.x = Random.Range(-0.35f, 0.22f);
                }
                /* Right */
                else if(touch.position.x > (Screen.width / 3) * 2 && touch.position.x <= Screen.width)
                {
                    ballPos.x = Random.Range(0.22f, 0.36f);
                }

                GameObject ball = Instantiate(ballReference, ballPos, transform.rotation) as GameObject;
                ball.rigidbody.AddForce(throwSpeed);

                AudioSource.PlayClipAtPoint(throwSound, transform.position);

                endPos = new Vector2(0, 0);
                startPos = new Vector2(0, 0);
                ballOnStage = true;
            }
        }
    }
}

23. BallSensor Class

The following script contains the implementation of the BallSensor class and is attached to the ball sensors, handling any collisions with the ball sensors.

Step 1: Declaring Variables

We start by declaring a variable named sensorValue, which stores the number of points the ball sensor will add to the score. Because the ball sensors are all the same prefab, we declare this variable as public. This will allow us to set this value in the editor using the Inspector.

using UnityEngine;
using System.Collections;

public class BallSensor : MonoBehaviour
{
    public int sensorValue = 0;
    public GUIText scoreReference;
    public GameObject alertReference;

The other two variables store references to the score and alert game objects, which we also set in Unity's InspectorThese references will be used to increase the score and display the alert when the game ends.

Step 2: Destroying the Ball

The OnTriggerEnter method detects when a collision has occurred and accepts the Collider object the sensor is colliding with, the ball in this case. When a collision is detected, the ball is destroyed to prevent it from bouncing and potentially falling in another hole.

void OnTriggerEnter(Collider other)
{
    Destroy(other.gameObject);

Step 3: Enabling Throw

After destroying the ball, we are sure that it isn't on the alley anymore. This means we can throw another ball without causing an unwanted behavior. The following line of code communicates with the ThrowBall class and gets the ballOnStage variable, setting it to false.

Camera.main.GetComponent<ThrowBall>().ballOnStage = false;

Let's take a closer look at how we access a variable declared in another class. As you can tell by now, one way to access a variable or object declared outside of the current class is to set a reference variable using public or [SerializeField], and then use the Inspector to give it a value.

The public keyword plays an important role in this. Using it makes the variable not only accessible from the Inspector, but also through code. To do this, we first need access to the GameObject that has the Script Component attached to it, which is the Main Camera in this case.

There is only one camera in this game, which makes things easier. We can get a reference to the main camera through Camera.main. Using GetComponent we get the script attached to the camera, using the name of the class. We then have access to the public variable named ballOnStage.

Step 4: Changing the Score

The following code block updates the score, using the reference we declared earlier.

scoreReference.text = (int.Parse(scoreReference.text) + sensorValue).ToString();

We convert the value stored in scoreReference to an integer and add it to the value stored in sensorValue. We convert the result to a string and assign it to the text property of scoreReference.

Step 5: Updating the Remaining Balls

In this step, we decrease the number of remaining balls. We use the method described in Step 3 to access the ballsLeft and ballsTextReference variables of the ThrowBall class.

Camera.main.GetComponent<ThrowBall>().ballsLeft--;
Camera.main.GetComponent<ThrowBall>().ballsTextReference.text = Camera.main.GetComponent<ThrowBall>().ballsLeft.ToString();

We decrement the value stored in ballsLeft and update the text property of ballsTextReference.

Step 6: Checking for Game Over

The game is over when the player runs out of available shots. The next lines of code check if the ballsLeft variable is equal to 0 and create an alert if true. We then call the Invoke method to invoke the Reload method, which restarts the game by reloading the current scene.

The second parameter of the Invoke method defines the delay with which the Reload method will be invoked. We do this to give the player some time before we start a new game.

    if (Camera.main.GetComponent<ThrowBall>().ballsLeft == 0)
    {
        Instantiate(alertReference, new Vector3(0.5f, 0.5f, 0), transform.rotation);
        Invoke("Reload", 3);
    }
}

Step 7: Reloading the Game

This is the last part of the BallSensor class. In the Reload method, we call LoadLevel on the Application class and reload the current level, resetting every object and variable to its initial state.

    void Reload()
    {
        Application.LoadLevel(Application.loadedLevel);
    }
}

This is what the class looks like when finished.

using UnityEngine;
using System.Collections;

public class BallSensor : MonoBehaviour
{
    public int sensorValue = 0;
    public GUIText scoreReference;
    public GameObject alertReference;

    void OnTriggerEnter(Collider other)
    {
        Destroy(other.gameObject);
        Camera.main.GetComponent<ThrowBall>().ballOnStage = false;
        scoreReference.text = (int.Parse(scoreReference.text) + sensorValue).ToString();

        Camera.main.GetComponent<ThrowBall>().ballsLeft--;
        Camera.main.GetComponent<ThrowBall>().ballsTextReference.text = Camera.main.GetComponent<ThrowBall>().ballsLeft.ToString();

        if (Camera.main.GetComponent<ThrowBall>().ballsLeft == 0)
        {
            Instantiate(alertReference, new Vector3(0.5f, 0.5f, 0), transform.rotation);
            Invoke("Reload", 3);
        }
    }

    void Reload()
    {
        Application.LoadLevel(Application.loadedLevel);
    }
}

24. Testing

It's time to test the game. Press Command-P to play the game in Unity. If everything works as expected, then you're ready for the final steps.

25. Player Settings

When you're happy with your game, it's time to select Build Settings from the File menu and click the Player Settings button. This should bring up the Player Settings in the Inspector panel where you can set the parameters for your application.

These settings are application specific data that includes the creator or company, app resolution and display mode, rendering mode (CPU, GPU), device OS compatibility, etc. Configure the settings according to the devices you're targeting and the store or market where you plan to publish the app.

26. Icons and Splash Images

Using the graphics you created earlier, you can now create a nice icon and a splash image for your game. Unity shows you the required sizes, which depend on the platform you're building for.

27. Build and Play


Once your project is properly configured, it's time to revisit the Build Settings and click the Build Button. That's all it takes to build your game for testing and/or distribution.

Conclusion

In this tutorial, we've learned how to use physics forces, swipe gestures, class communication, and other aspects of game development in Unity. I encourage you to experiment with the result and customize the game to make it your own. I hope you liked this tutorial and found it helpful.

2014-09-26T16:45:19.000Z2014-09-26T16:45:19.000ZCarlos Yanez

Core Data from Scratch: Concurrency

$
0
0

If you're developing a small or simple application, then you probably don't see the benefit of running Core Data operations in the background. However, what would happen if you imported hundreds or thousands of records on the main thread during the first launch of your application? The consequences could be dramatic. For example, your application could be killed by Apple's watchdog for taking too long to launch.

In this article, we take a look at the dangers when using Core Data on multiple threads and we explore several solutions to tackle the problem.

1. Thread Safety

When working with Core Data, it's important to always remember that Core Data isn't thread safe. Core Data expects to be run on a single thread. This doesn't mean that every Core Data operation needs to be performed on the main thread, which is true for UIKit, but it does mean that you need to be aware which operations are executed on which threads. It also means that you need to be careful how changes from one thread are propagated to other threads.

Working with Core Data on multiple threads is actually very simple from a theoretical point of view. NSManagedObjectNSManagedObjectContext, and NSPersistentStoreCoordinator aren't thread safe, and instances of these classes should only be accessed from the thread they were created on. As you can imagine, this becomes a bit more complex in practice.

NSManagedObject

We already know that the NSManagedObject class isn't thread safe, but how do you access a record from different threads? An NSManagedObject instance has an objectID method that returns an instance of the NSManagedObjectID class. The NSManagedObjectID class is thread safe and an instance contains all the information a managed object context needs to fetch the corresponding managed object.

// Object ID Managed Object
NSManagedObjectID *objectID = [managedObject objectID];

In the following code snippet, we ask a managed object context for the managed object that corresponds with objectID. The objectWithID: and existingObjectWithID:error: methods return a local version—local to the current thread—of the corresponding managed object.

// Fetch Managed Object
NSManagedObject *managedObject = [self.managedObjectContext objectWithID:objectID];

// OR

// Fetch Managed Object
NSError *error = nil;
NSManagedObject *managedObject = [self.managedObjectContext existingObjectWithID:objectID error:&error];

if (error) {
    NSLog(@"Unable to fetch managed object with object ID, %@.", objectID);
    NSLog(@"%@, %@", error, error.localizedDescription);
}

The basic rule to remember is to not pass the NSManagedObject instance from one thread to another. Instead, pass the managed object's objectID and ask the thread's managed object context for a local version of the managed object.

NSManagedObjectContext

Because the NSManagedObjectContext class isn't thread safe, we could create a managed object context for every thread that interacts with Core Data. This strategy is often referred to as thread confinement.

A common approach is to store the managed object context in the thread's dictionary, a dictionary to store thread-specific data. Take a look at the following example to see how this works in practice.

// Add Object to Thread Dictionary
NSThread *currentThread = [NSThread currentThread];
[[currentThread threadDictionary] setObject:managedObjectContext forKey:@"managedObjectContext"];

NSPersistentStoreCoordinator

What about the persistent store coordinator? Do you need to create a separate persistent store coordinator for every thread. While this is possible and one of the strategies Apple used to recommend, it isn't necessary.

The NSPersistentStoreCoordinator class was designed to support multiple managed object contexts, even if those managed object contexts were created on different threads. Because the NSManagedObjectContext class locks the persistent store coordinator while accessing it, it is possible for multiple managed object contexts to use the same persistent store coordinator even if those managed object contexts live on different threads. This makes a multithreaded Core Data setup much more manageable and less complex.

2. Concurrency Strategies

So far, we've learned that you need multiple managed object contexts if you perform Core Data operations on multiple threads. The caveat, however, is that managed object contexts are unaware of each others existence. Changes made to a managed object in one managed object context are not automatically propagated to other managed object contexts. How do we solve this problem?

There are two popular strategies that Apple recommends, notifications and parent-child managed object contexts. Let's look at each strategy and investigate their pros and cons.

The scenario we'll take as an example is an NSOperation subclass that performs work in the background and accesses Core Data on the operation's background thread. This example will show you the differences and advantages of each strategy.

Strategy 1: Notifications

Earlier in this series, I introduced you to the NSFetchedResultsController class and you learned that a managed object context posts three types of notifications:

  • NSManagedObjectContextObjectsDidChangeNotification: this notification is posted when one of the managed objects of the managed object context has changed
  • NSManagedObjectContextWillSaveNotification: this notification is posted before the managed object context performs a save operation
  • NSManagedObjectContextDidSaveNotification: this notification is posted after the managed object context performs a save operation

When a managed object context saves its changes to a persistent store, via the persistent store coordinator, other managed object contexts may want to know about those changes. This is very easy to do and it's even easier to include or merge the changes into another managed object context. Let's talk code.

We create a non-concurrent operation that does some work in the background and needs access to Core Data. The header would look similar to the one shown below.

#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>

@interface TSPImportOperation : NSOperation

@property (strong, nonatomic) NSManagedObjectContext *mainManagedObjectContext;

@end

The operation's interface is very simple as it only contains a property for the application's main managed object context. There are several reasons for keeping a reference to the application's main managed object context. This becomes clear when we inspect the implementation of the TSPImportOperation class.

We first declare a private property, privateManagedObjectContext, of type NSManagedObjectContext. This is the managed object context that the operation will use internally to perform Core Data tasks.

#import "TSPImportOperation.h"

@interface TSPImportOperation ()

@property (strong, nonatomic) NSManagedObjectContext *privateManagedObjectContext;

@end

Because we're implementing a non-concurrent NSOperation subclass, we need to implement the main method. This is what it looks like.

- (void)main {
    // Initialize Managed Object Context
    self.privateManagedObjectContext = [[NSManagedObjectContext alloc] init];
    // Configure Managed Object Context
    [self.privateManagedObjectContext setPersistentStoreCoordinator:self.mainManagedObjectContext.persistentStoreCoordinator];
    // Add Observer
    NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
    [nc addObserver:self selector:@selector(managedObjectContextDidSave:) name:NSManagedObjectContextDidSaveNotification object:self.privateManagedObjectContext];
    // Do Some Work
    // ...
    if ([self.privateManagedObjectContext hasChanges]) {
        // Save Changes
        NSError *error = nil;
        [self.privateManagedObjectContext save:&error];
    }
}

There are a few important details that need to be clarified. We initialize the private managed object context and set its persistent store coordinator property using the mainManagedObjectContext object. This is perfectly fine, because we don't access the mainManagedObjectContext, we only ask it for its reference to the application's persistent store coordinator. We don't violate the thread confinement rule.

It is essential to initialize the private managed object context in the operation's main method, because this method is executed on the background thread on which the operation runs. Can't we initialize the managed object context in the operation's init method? The answer is no. The operation's init method is run on the thread on which the TSPImportOperation is initialized, which is most likely the main thread. This would defeat the purpose of a private managed object context.

In the operation's main method, we add the TSPImportOperation instance as an observer of any NSManagedObjectContextDidSaveNotification notifications posted by the private managed object context.

We then do the work the operation was created for and save the changes of the private managed object context, which will trigger a NSManagedObjectContextDidSaveNotification notification. Let's take a look at what happens in the managedObjectContextDidSave: method.

#pragma mark -
#pragma mark Notification Handling
- (void)managedObjectContextDidSave:(NSNotification *)notification {
    dispatch_async(dispatch_get_main_queue(), ^{
        [self.mainManagedObjectContext mergeChangesFromContextDidSaveNotification:notification];
    });
}

As you can see, its implementation is short and simple. We call mergeChangesFromContextDidSaveNotification: on the main managed object context, passing in the notification object. As I mentioned earlier, the notification contains the changes, inserts, updates, and deletes, of the private managed object context. It is key to call this method on the thread the main managed object context was created on, the main thread. That's why we dispatch this call to the main thread.

Putting the TSPImportOperation class to use is as simple as initializing an instance, setting its mainManagedObjectContext property, and adding the operation to an operation queue.

// Initialize Import Operation
TSPImportOperation *operation = [[TSPImportOperation alloc] init];

// Configure Import Operation
[operation setMainManagedObjectContext:self.managedObjectContext];

// Add to Operation Queue
[self.operationQueue addOperation:operation];

Strategy 2: Parent/Child Managed Object Contexts

Since iOS 6, there's an even better, more elegant strategy. Let's revisit the TSPImportOperation class and leverage parent/child managed object contexts. The concept behind parent/child managed object contexts is simple but powerful. Let me explain how it works.

A child managed object context is dependent on its parent managed object context for saving its changes to the corresponding persistent store. In fact, a child managed object context doesn't have access to a persistent store coordinator. Whenever a child managed object context is saved, the changes it contains are pushed to the parent managed object context. There's no need to use notifications to manually merge the changes into the main or parent managed object context.

Another benefit is performance. Because the child managed object context doesn't have access to the persistent store coordinator, the changes aren't pushed to the latter when the child managed object context is saved. Instead, the changes are pushed to the parent managed object context, dirtying it. The changes are not automatically propagated to the persistent store coordinator.

Managed object contexts can be nested. A child managed object context can have a child managed object context of its own. The same rules apply. However, it's important to remember that the changes that are pushed up to the parent managed object context are not pushed down to any other child managed object contexts. If child A pushed its changes to its parent, then child B is unaware of these changes.

Creating a child managed object context is slightly different from what we've seen so far. A child managed object context uses a different initializer, initWithConcurrencyType:. The concurrency type the initializer accepts defines the managed object context's threading model. Let's look at each concurrency type.

  • NSMainQueueConcurrencyType: The managed object context is only accessible from the main thread. An exception is thrown if you try to access it from any other thread.
  • NSPrivateQueueConcurrencyType: When creating a managed object context with a concurrency type of NSPrivateQueueConcurrencyType, the managed object context is associated with a private queue and it can only be accessed from that private queue.
  • NSConfinementConcurrencyType: This is the concurrency type that corresponds with the thread confinement concept we explored earlier. If you create a managed object context using the init method, the concurrency type of that managed object context is NSConfinementConcurrencyType.

There are two key methods that were added to the Core Data framework when Apple introduced parent/child managed object contexts, performBlock: and performBlockAndWait:. Both methods will make your life much easier. When you call performBlock: on a managed object context and pass in a block of code to execute, Core Data makes sure that the block is executed on the correct thread. In the case of the NSPrivateQueueConcurrencyType concurrency type, this means that the block is executed on the private queue of that managed object context.

The difference between performBlock: and performBlockAndWait: is simple. The performBlock: method doesn't block the current thread. It accepts the block, schedules it for execution on the correct queue, and continues with the execution of the next statement.

The performBlockAndWait: method, however, is blocking. The thread from which performBlockAndWait: is called waits for the block that is passed to the method to finish before executing the next statement. The advantage is that nested calls to performBlockAndWait: are executed in order.

To end this article, I'd like to refactor the TSPImportOperation class to take advantage of parent/child managed object contexts. You'll quickly notice that it greatly simplifies the TSPImportOperation subclass.

The header remains unchanged, but the main method changes quite a bit. Take a look at its updated implementation below.

- (void)main {
    // Initialize Managed Object Context
    self.privateManagedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
    // Configure Managed Object Context
    [self.privateManagedObjectContext setParentContext:self.mainManagedObjectContext];
    // Do Some Work
    // ...
    if ([self.privateManagedObjectContext hasChanges]) {
        // Save Changes
        NSError *error = nil;
        [self.privateManagedObjectContext save:&error];
    }
}

That's it. The main managed object context is the parent of the private managed object context. Note that we don't set the persistentStoreCoordinator property of the private managed object context and we don't add the operation as an observer for NSManagedObjectContextDidSaveNotification notifications. When the private managed object context is saved, the changes are automatically pushed to its parent managed object context. Core Data ensures that this happens on the correct thread. It's up to the main managed object context, the parent managed object context, to push the changes to the persistent store coordinator.

Conclusion

Concurrency isn't easy to grasp or implement, but it's naive to think that you'll never come across a situation in which you need to perform Core Data operations on a background thread.

In the next two articles, I'll tell you about iOS 8 and Core Data. Apple introduced a number of new APIs in iOS 8 and OS X 10.10, including batch updating and asynchronous fetching.

2014-09-29T18:05:37.000Z2014-09-29T18:05:37.000ZBart Jacobs

Core Data from Scratch: Concurrency

$
0
0
tag:code.tutsplus.com,2005:PostPresenter/cms-22131

If you're developing a small or simple application, then you probably don't see the benefit of running Core Data operations in the background. However, what would happen if you imported hundreds or thousands of records on the main thread during the first launch of your application? The consequences could be dramatic. For example, your application could be killed by Apple's watchdog for taking too long to launch.

In this article, we take a look at the dangers when using Core Data on multiple threads and we explore several solutions to tackle the problem.

1. Thread Safety

When working with Core Data, it's important to always remember that Core Data isn't thread safe. Core Data expects to be run on a single thread. This doesn't mean that every Core Data operation needs to be performed on the main thread, which is true for UIKit, but it does mean that you need to be aware which operations are executed on which threads. It also means that you need to be careful how changes from one thread are propagated to other threads.

Working with Core Data on multiple threads is actually very simple from a theoretical point of view. NSManagedObjectNSManagedObjectContext, and NSPersistentStoreCoordinator aren't thread safe, and instances of these classes should only be accessed from the thread they were created on. As you can imagine, this becomes a bit more complex in practice.

NSManagedObject

We already know that the NSManagedObject class isn't thread safe, but how do you access a record from different threads? An NSManagedObject instance has an objectID method that returns an instance of the NSManagedObjectID class. The NSManagedObjectID class is thread safe and an instance contains all the information a managed object context needs to fetch the corresponding managed object.

// Object ID Managed Object
NSManagedObjectID *objectID = [managedObject objectID];

In the following code snippet, we ask a managed object context for the managed object that corresponds with objectID. The objectWithID: and existingObjectWithID:error: methods return a local version—local to the current thread—of the corresponding managed object.

// Fetch Managed Object
NSManagedObject *managedObject = [self.managedObjectContext objectWithID:objectID];

// OR

// Fetch Managed Object
NSError *error = nil;
NSManagedObject *managedObject = [self.managedObjectContext existingObjectWithID:objectID error:&error];

if (error) {
    NSLog(@"Unable to fetch managed object with object ID, %@.", objectID);
    NSLog(@"%@, %@", error, error.localizedDescription);
}

The basic rule to remember is to not pass the NSManagedObject instance from one thread to another. Instead, pass the managed object's objectID and ask the thread's managed object context for a local version of the managed object.

NSManagedObjectContext

Because the NSManagedObjectContext class isn't thread safe, we could create a managed object context for every thread that interacts with Core Data. This strategy is often referred to as thread confinement.

A common approach is to store the managed object context in the thread's dictionary, a dictionary to store thread-specific data. Take a look at the following example to see how this works in practice.

// Add Object to Thread Dictionary
NSThread *currentThread = [NSThread currentThread];
[[currentThread threadDictionary] setObject:managedObjectContext forKey:@"managedObjectContext"];

NSPersistentStoreCoordinator

What about the persistent store coordinator? Do you need to create a separate persistent store coordinator for every thread. While this is possible and one of the strategies Apple used to recommend, it isn't necessary.

The NSPersistentStoreCoordinator class was designed to support multiple managed object contexts, even if those managed object contexts were created on different threads. Because the NSManagedObjectContext class locks the persistent store coordinator while accessing it, it is possible for multiple managed object contexts to use the same persistent store coordinator even if those managed object contexts live on different threads. This makes a multithreaded Core Data setup much more manageable and less complex.

2. Concurrency Strategies

So far, we've learned that you need multiple managed object contexts if you perform Core Data operations on multiple threads. The caveat, however, is that managed object contexts are unaware of each others existence. Changes made to a managed object in one managed object context are not automatically propagated to other managed object contexts. How do we solve this problem?

There are two popular strategies that Apple recommends, notifications and parent-child managed object contexts. Let's look at each strategy and investigate their pros and cons.

The scenario we'll take as an example is an NSOperation subclass that performs work in the background and accesses Core Data on the operation's background thread. This example will show you the differences and advantages of each strategy.

Strategy 1: Notifications

Earlier in this series, I introduced you to the NSFetchedResultsController class and you learned that a managed object context posts three types of notifications:

  • NSManagedObjectContextObjectsDidChangeNotification: this notification is posted when one of the managed objects of the managed object context has changed
  • NSManagedObjectContextWillSaveNotification: this notification is posted before the managed object context performs a save operation
  • NSManagedObjectContextDidSaveNotification: this notification is posted after the managed object context performs a save operation

When a managed object context saves its changes to a persistent store, via the persistent store coordinator, other managed object contexts may want to know about those changes. This is very easy to do and it's even easier to include or merge the changes into another managed object context. Let's talk code.

We create a non-concurrent operation that does some work in the background and needs access to Core Data. The header would look similar to the one shown below.

#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>

@interface TSPImportOperation : NSOperation

@property (strong, nonatomic) NSManagedObjectContext *mainManagedObjectContext;

@end

The operation's interface is very simple as it only contains a property for the application's main managed object context. There are several reasons for keeping a reference to the application's main managed object context. This becomes clear when we inspect the implementation of the TSPImportOperation class.

We first declare a private property, privateManagedObjectContext, of type NSManagedObjectContext. This is the managed object context that the operation will use internally to perform Core Data tasks.

#import "TSPImportOperation.h"

@interface TSPImportOperation ()

@property (strong, nonatomic) NSManagedObjectContext *privateManagedObjectContext;

@end

Because we're implementing a non-concurrent NSOperation subclass, we need to implement the main method. This is what it looks like.

- (void)main {
    // Initialize Managed Object Context
    self.privateManagedObjectContext = [[NSManagedObjectContext alloc] init];
    // Configure Managed Object Context
    [self.privateManagedObjectContext setPersistentStoreCoordinator:self.mainManagedObjectContext.persistentStoreCoordinator];
    // Add Observer
    NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
    [nc addObserver:self selector:@selector(managedObjectContextDidSave:) name:NSManagedObjectContextDidSaveNotification object:self.privateManagedObjectContext];
    // Do Some Work
    // ...
    if ([self.privateManagedObjectContext hasChanges]) {
        // Save Changes
        NSError *error = nil;
        [self.privateManagedObjectContext save:&error];
    }
}

There are a few important details that need to be clarified. We initialize the private managed object context and set its persistent store coordinator property using the mainManagedObjectContext object. This is perfectly fine, because we don't access the mainManagedObjectContext, we only ask it for its reference to the application's persistent store coordinator. We don't violate the thread confinement rule.

It is essential to initialize the private managed object context in the operation's main method, because this method is executed on the background thread on which the operation runs. Can't we initialize the managed object context in the operation's init method? The answer is no. The operation's init method is run on the thread on which the TSPImportOperation is initialized, which is most likely the main thread. This would defeat the purpose of a private managed object context.

In the operation's main method, we add the TSPImportOperation instance as an observer of any NSManagedObjectContextDidSaveNotification notifications posted by the private managed object context.

We then do the work the operation was created for and save the changes of the private managed object context, which will trigger a NSManagedObjectContextDidSaveNotification notification. Let's take a look at what happens in the managedObjectContextDidSave: method.

#pragma mark -
#pragma mark Notification Handling
- (void)managedObjectContextDidSave:(NSNotification *)notification {
    dispatch_async(dispatch_get_main_queue(), ^{
        [self.mainManagedObjectContext mergeChangesFromContextDidSaveNotification:notification];
    });
}

As you can see, its implementation is short and simple. We call mergeChangesFromContextDidSaveNotification: on the main managed object context, passing in the notification object. As I mentioned earlier, the notification contains the changes, inserts, updates, and deletes, of the private managed object context. It is key to call this method on the thread the main managed object context was created on, the main thread. That's why we dispatch this call to the main thread.

Putting the TSPImportOperation class to use is as simple as initializing an instance, setting its mainManagedObjectContext property, and adding the operation to an operation queue.

// Initialize Import Operation
TSPImportOperation *operation = [[TSPImportOperation alloc] init];

// Configure Import Operation
[operation setMainManagedObjectContext:self.managedObjectContext];

// Add to Operation Queue
[self.operationQueue addOperation:operation];

Strategy 2: Parent/Child Managed Object Contexts

Since iOS 6, there's an even better, more elegant strategy. Let's revisit the TSPImportOperation class and leverage parent/child managed object contexts. The concept behind parent/child managed object contexts is simple but powerful. Let me explain how it works.

A child managed object context is dependent on its parent managed object context for saving its changes to the corresponding persistent store. In fact, a child managed object context doesn't have access to a persistent store coordinator. Whenever a child managed object context is saved, the changes it contains are pushed to the parent managed object context. There's no need to use notifications to manually merge the changes into the main or parent managed object context.

Another benefit is performance. Because the child managed object context doesn't have access to the persistent store coordinator, the changes aren't pushed to the latter when the child managed object context is saved. Instead, the changes are pushed to the parent managed object context, dirtying it. The changes are not automatically propagated to the persistent store coordinator.

Managed object contexts can be nested. A child managed object context can have a child managed object context of its own. The same rules apply. However, it's important to remember that the changes that are pushed up to the parent managed object context are not pushed down to any other child managed object contexts. If child A pushed its changes to its parent, then child B is unaware of these changes.

Creating a child managed object context is slightly different from what we've seen so far. A child managed object context uses a different initializer, initWithConcurrencyType:. The concurrency type the initializer accepts defines the managed object context's threading model. Let's look at each concurrency type.

  • NSMainQueueConcurrencyType: The managed object context is only accessible from the main thread. An exception is thrown if you try to access it from any other thread.
  • NSPrivateQueueConcurrencyType: When creating a managed object context with a concurrency type of NSPrivateQueueConcurrencyType, the managed object context is associated with a private queue and it can only be accessed from that private queue.
  • NSConfinementConcurrencyType: This is the concurrency type that corresponds with the thread confinement concept we explored earlier. If you create a managed object context using the init method, the concurrency type of that managed object context is NSConfinementConcurrencyType.

There are two key methods that were added to the Core Data framework when Apple introduced parent/child managed object contexts, performBlock: and performBlockAndWait:. Both methods will make your life much easier. When you call performBlock: on a managed object context and pass in a block of code to execute, Core Data makes sure that the block is executed on the correct thread. In the case of the NSPrivateQueueConcurrencyType concurrency type, this means that the block is executed on the private queue of that managed object context.

The difference between performBlock: and performBlockAndWait: is simple. The performBlock: method doesn't block the current thread. It accepts the block, schedules it for execution on the correct queue, and continues with the execution of the next statement.

The performBlockAndWait: method, however, is blocking. The thread from which performBlockAndWait: is called waits for the block that is passed to the method to finish before executing the next statement. The advantage is that nested calls to performBlockAndWait: are executed in order.

To end this article, I'd like to refactor the TSPImportOperation class to take advantage of parent/child managed object contexts. You'll quickly notice that it greatly simplifies the TSPImportOperation subclass.

The header remains unchanged, but the main method changes quite a bit. Take a look at its updated implementation below.

- (void)main {
    // Initialize Managed Object Context
    self.privateManagedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
    // Configure Managed Object Context
    [self.privateManagedObjectContext setParentContext:self.mainManagedObjectContext];
    // Do Some Work
    // ...
    if ([self.privateManagedObjectContext hasChanges]) {
        // Save Changes
        NSError *error = nil;
        [self.privateManagedObjectContext save:&error];
    }
}

That's it. The main managed object context is the parent of the private managed object context. Note that we don't set the persistentStoreCoordinator property of the private managed object context and we don't add the operation as an observer for NSManagedObjectContextDidSaveNotification notifications. When the private managed object context is saved, the changes are automatically pushed to its parent managed object context. Core Data ensures that this happens on the correct thread. It's up to the main managed object context, the parent managed object context, to push the changes to the persistent store coordinator.

Conclusion

Concurrency isn't easy to grasp or implement, but it's naive to think that you'll never come across a situation in which you need to perform Core Data operations on a background thread.

In the next two articles, I'll tell you about iOS 8 and Core Data. Apple introduced a number of new APIs in iOS 8 and OS X 10.10, including batch updating and asynchronous fetching.

2014-09-29T18:05:37.000Z2014-09-29T18:05:37.000ZBart Jacobs

iOS 8: Core Data and Batch Updates

$
0
0

Core Data has been around for many years on OS X and it didn't take Apple long to bring it to iOS. Even though the framework doesn't get as much attention as extensions or handoff, it continues to evolve year over year, and this year, with the release of iOS 8 and OS X Yosemite, is no different.

Apple introduced a few new features to the Core Data framework, but the most notable are batch updates and asynchronous fetching. Developers have been asking for these features for many years and Apple finally found a way to integrate them into Core Data. In this tutorial, I will show you how batch updates work and what they mean for the Core Data framework.

1. The Problem

Core Data is great at managing object graphs. Even complex object graphs with many entities and relationships aren't much of a problem for Core Data. However, Core Data does have a few weak spots and updating a large number of records is one of them.

The problem is easy to understand. Whenever you update a record, Core Data loads the record into memory, updates the record, and save the changes to the persistent store, a SQLite database for example.

If Core Data needs to update a large number of records, it needs to load every single record into memory, update the record, and send the changes to the persistent store. If the number of records is too large, iOS will simply bail out due to a lack of resources. Even though a device running OS X may have the resources to execute the request, it will be slow and consume a lot of memory.

An alternative approach is to update the records in batches, but that too takes a lot of time and resources. On iOS 7, it's the only option iOS developers have. That is no longer the case on iOS 8.

2. The Solution

On iOS 8 and OS X Yosemite, it's possible to talk directly to the persistent store and tell it what you'd like to change. This generally involves updating an attribute or deleting a number of records. Apple calls this feature batch updates.

There are a number of pitfalls to watch out for though. Core Data does a lot of things for you and you may not even realize it until you use batch updates. Validation is a good example. Because Core Data performs batch updates directly on the persistent store, such as a SQLite database, Core Data isn't able to perform any validation on the data you insert. This means that you are in charge of making sure you don't add invalid data to the persistent store.

When would you use batch updates? Apple recommends to only use this feature if the traditional approach is too resource or time intensive. If you need to mark hundreds or thousands of email messages as read, then batch updates is the best solution on iOS 8 and OS X Yosemite.

3. How Does It Work?

To illustrate how batch updates work, I suggest we revisit Done, a simple Core Data application that manages a to-do list. We'll add a button to the navigation bar that marks every item in the list as done.

Step 1: Projet Setup

Download or clone the project from GitHub and open it in Xcode 6. Run the application in the iOS Simulator and add a few to-do items.

Step 2: Create Bar Button Item

Open TSPViewController.m and declare a property, checkAllButton, of type UIBarButtonItem in the private class extension at the top.

@interface TSPViewController () <NSFetchedResultsControllerDelegate>

@property (strong, nonatomic) NSFetchedResultsController *fetchedResultsController;

@property (strong, nonatomic) UIBarButtonItem *checkAllButton;

@property (strong, nonatomic) NSIndexPath *selection;

@end

Initialize the bar button item in the viewDidLoad method of the TSPViewController class and set it as the left bar button item of the navigation item.

// Initialize Check All Button
self.checkAllButton = [[UIBarButtonItem alloc] initWithTitle:@"Check All" style:UIBarButtonItemStyleBordered target:self action:@selector(checkAll:)];
// Configure Navigation Item
self.navigationItem.leftBarButtonItem = self.checkAllButton;

Step 3: Implement checkAll: Method

The checkAll: method is fairly easy, but there are a few caveats to watch out for. Take a look at its implementation below.

- (void)checkAll:(id)sender {
    // Create Entity Description
    NSEntityDescription *entityDescription = [NSEntityDescription entityForName:@"TSPItem" inManagedObjectContext:self.managedObjectContext];
    // Initialize Batch Update Request
    NSBatchUpdateRequest *batchUpdateRequest = [[NSBatchUpdateRequest alloc] initWithEntity:entityDescription];
    // Configure Batch Update Request
    [batchUpdateRequest setResultType:NSUpdatedObjectIDsResultType];
    [batchUpdateRequest setPropertiesToUpdate:@{ @"done" : @YES }];
    // Execute Batch Request
    NSError *batchUpdateRequestError = nil;
    NSBatchUpdateResult *batchUpdateResult = (NSBatchUpdateResult *)[self.managedObjectContext executeRequest:batchUpdateRequest error:&batchUpdateRequestError];
    if (batchUpdateRequestError) {
        NSLog(@"Unable to execute batch update request.");
        NSLog(@"%@, %@", batchUpdateRequestError, batchUpdateRequestError.localizedDescription);
    } else {
        // Extract Object IDs
        NSArray *objectIDs = batchUpdateResult.result;
        for (NSManagedObjectID *objectID in objectIDs) {
            // Turn Managed Objects into Faults
            NSManagedObject *managedObject = [self.managedObjectContext objectWithID:objectID];
            if (managedObject) {
                [self.managedObjectContext refreshObject:managedObject mergeChanges:NO];
            }
        }
        // Perform Fetch
        NSError *fetchError = nil;
        [self.fetchedResultsController performFetch:&fetchError];
        if (fetchError) {
            NSLog(@"Unable to perform fetch.");
            NSLog(@"%@, %@", fetchError, fetchError.localizedDescription);
        }
    }
}

Create Batch Request

We start by creating an NSEntityDescription instance for the TSPItem entity and use it to initialize a NSBatchUpdateRequest object.

// Create Entity Description
NSEntityDescription *entityDescription = [NSEntityDescription entityForName:@"TSPItem" inManagedObjectContext:self.managedObjectContext];

// Initialize Batch Update Request
NSBatchUpdateRequest *batchUpdateRequest = [[NSBatchUpdateRequest alloc] initWithEntity:entityDescription];

We set the result type of the batch update request to NSUpdatedObjectIDsResultType, which means that the result of the batch update request will be an array containing the object IDs, instances of the NSManagedObjectID class, of the records that were changed by the batch update request.

// Configure Batch Update Request
[batchUpdateRequest setResultType:NSUpdatedObjectIDsResultType];

We also populate the propertiesToUpdate property of the batch update request. For this example, we set propertiesToUpdate to an NSDictionary containing one key, @"done", with value @YES. This simply means that every TSPItem record will be set to done, which is exactly what we want.

// Configure Batch Update Request
[batchUpdateRequest setPropertiesToUpdate:@{ @"done" : @YES }];

Execute Batch Update Request

Even though batch updates bypass the managed object context, executing a batch update request is done by calling executeRequest:error: on a NSManagedObjectContext instance. The first argument is an instance of the NSPersistentStoreRequest class. To execute a batch update, we pass the batch update request we just created. This works fins since the NSBatchUpdateRequest class is a NSPersistentStoreRequest subclass. The second argument is a pointer to an NSError object.

// Execute Batch Request
NSError *batchUpdateRequestError = nil;
NSBatchUpdateResult *batchUpdateResult = (NSBatchUpdateResult *)[self.managedObjectContext executeRequest:batchUpdateRequest error:&batchUpdateRequestError];

Updating the Managed Object Context

As I mentioned earlier, batch updates bypass the managed object context. This gives batch updates their power and speed, but it also means that the managed object context isn't aware of the changes we made. To remedy this issue, we need to do two things:

  • turn the managed objects that were updated by the batch update into faults
  • tell the fetched results controller to perform a fetch to update the user interface

This is what we do in the next few lines of the checkAll: method. We first check if the batch update request was successful by checking the batchUpdateRequestError for nil. If successful, we extract the array of NSManagedObjectID instances from the NSBatchUpdateResult object.

// Extract Object IDs
NSArray *objectIDs = batchUpdateResult.result;

We then iterate over the objectIDs array and ask the managed object context for the corresponding NSManagedObject instance. If the managed object context returns a valid managed object, we turn it into a fault by invoking refreshObject:mergeChanges:, passing in the managed object as the first argument. To force the managed object into a fault, we pass NO as the second argument.

// Extract Object IDs
NSArray *objectIDs = batchUpdateResult.result;

for (NSManagedObjectID *objectID in objectIDs) {
    // Turn Managed Objects into Faults
    NSManagedObject *managedObject = [self.managedObjectContext objectWithID:objectID];
    
    if (managedObject) {
        [self.managedObjectContext refreshObject:managedObject mergeChanges:NO];
    }
}

Fetching Updated Records

The last step is to tell the fetched results controller to perform a fetch to update the user interface. If this is unsuccessful, we log the corresponding error.

// Perform Fetch
NSError *fetchError = nil;
[self.fetchedResultsController performFetch:&fetchError];

if (fetchError) {
    NSLog(@"Unable to perform fetch.");
    NSLog(@"%@, %@", fetchError, fetchError.localizedDescription);
}

While this may seem cumbersome and fairly complex for an easy operation, keep in mind that we bypass the Core Data stack. In other words, we need to take care of some housekeeping that's usually done for us by Core Data.

Step 4: Build & Run

Build the project and run the application in the iOS Simulator or on a physical device. Click or tap the bar button item on the right to check every to-do item in the list.

Conclusion

Batch updates are a great addition to the Core Data framework. Not only does it answer a need developers have had for many years, it isn't difficult to implement as long as you keep a few basic rules in mind. In the next tutorial, we'll take a closer look at asynchronous fetching, another new feature of the Core Data framework.

2014-09-30T16:15:59.000Z2014-09-30T16:15:59.000ZBart Jacobs

iOS 8: Core Data and Batch Updates

$
0
0
tag:code.tutsplus.com,2005:PostPresenter/cms-22164

Core Data has been around for many years on OS X and it didn't take Apple long to bring it to iOS. Even though the framework doesn't get as much attention as extensions or handoff, it continues to evolve year over year, and this year, with the release of iOS 8 and OS X Yosemite, is no different.

Apple introduced a few new features to the Core Data framework, but the most notable are batch updates and asynchronous fetching. Developers have been asking for these features for many years and Apple finally found a way to integrate them into Core Data. In this tutorial, I will show you how batch updates work and what they mean for the Core Data framework.

1. The Problem

Core Data is great at managing object graphs. Even complex object graphs with many entities and relationships aren't much of a problem for Core Data. However, Core Data does have a few weak spots and updating a large number of records is one of them.

The problem is easy to understand. Whenever you update a record, Core Data loads the record into memory, updates the record, and save the changes to the persistent store, a SQLite database for example.

If Core Data needs to update a large number of records, it needs to load every single record into memory, update the record, and send the changes to the persistent store. If the number of records is too large, iOS will simply bail out due to a lack of resources. Even though a device running OS X may have the resources to execute the request, it will be slow and consume a lot of memory.

An alternative approach is to update the records in batches, but that too takes a lot of time and resources. On iOS 7, it's the only option iOS developers have. That is no longer the case on iOS 8.

2. The Solution

On iOS 8 and OS X Yosemite, it's possible to talk directly to the persistent store and tell it what you'd like to change. This generally involves updating an attribute or deleting a number of records. Apple calls this feature batch updates.

There are a number of pitfalls to watch out for though. Core Data does a lot of things for you and you may not even realize it until you use batch updates. Validation is a good example. Because Core Data performs batch updates directly on the persistent store, such as a SQLite database, Core Data isn't able to perform any validation on the data you insert. This means that you are in charge of making sure you don't add invalid data to the persistent store.

When would you use batch updates? Apple recommends to only use this feature if the traditional approach is too resource or time intensive. If you need to mark hundreds or thousands of email messages as read, then batch updates is the best solution on iOS 8 and OS X Yosemite.

3. How Does It Work?

To illustrate how batch updates work, I suggest we revisit Done, a simple Core Data application that manages a to-do list. We'll add a button to the navigation bar that marks every item in the list as done.

Step 1: Projet Setup

Download or clone the project from GitHub and open it in Xcode 6. Run the application in the iOS Simulator and add a few to-do items.

Step 2: Create Bar Button Item

Open TSPViewController.m and declare a property, checkAllButton, of type UIBarButtonItem in the private class extension at the top.

@interface TSPViewController () <NSFetchedResultsControllerDelegate>

@property (strong, nonatomic) NSFetchedResultsController *fetchedResultsController;

@property (strong, nonatomic) UIBarButtonItem *checkAllButton;

@property (strong, nonatomic) NSIndexPath *selection;

@end

Initialize the bar button item in the viewDidLoad method of the TSPViewController class and set it as the left bar button item of the navigation item.

// Initialize Check All Button
self.checkAllButton = [[UIBarButtonItem alloc] initWithTitle:@"Check All" style:UIBarButtonItemStyleBordered target:self action:@selector(checkAll:)];
// Configure Navigation Item
self.navigationItem.leftBarButtonItem = self.checkAllButton;

Step 3: Implement checkAll: Method

The checkAll: method is fairly easy, but there are a few caveats to watch out for. Take a look at its implementation below.

- (void)checkAll:(id)sender {
    // Create Entity Description
    NSEntityDescription *entityDescription = [NSEntityDescription entityForName:@"TSPItem" inManagedObjectContext:self.managedObjectContext];
    // Initialize Batch Update Request
    NSBatchUpdateRequest *batchUpdateRequest = [[NSBatchUpdateRequest alloc] initWithEntity:entityDescription];
    // Configure Batch Update Request
    [batchUpdateRequest setResultType:NSUpdatedObjectIDsResultType];
    [batchUpdateRequest setPropertiesToUpdate:@{ @"done" : @YES }];
    // Execute Batch Request
    NSError *batchUpdateRequestError = nil;
    NSBatchUpdateResult *batchUpdateResult = (NSBatchUpdateResult *)[self.managedObjectContext executeRequest:batchUpdateRequest error:&batchUpdateRequestError];
    if (batchUpdateRequestError) {
        NSLog(@"Unable to execute batch update request.");
        NSLog(@"%@, %@", batchUpdateRequestError, batchUpdateRequestError.localizedDescription);
    } else {
        // Extract Object IDs
        NSArray *objectIDs = batchUpdateResult.result;
        for (NSManagedObjectID *objectID in objectIDs) {
            // Turn Managed Objects into Faults
            NSManagedObject *managedObject = [self.managedObjectContext objectWithID:objectID];
            if (managedObject) {
                [self.managedObjectContext refreshObject:managedObject mergeChanges:NO];
            }
        }
        // Perform Fetch
        NSError *fetchError = nil;
        [self.fetchedResultsController performFetch:&fetchError];
        if (fetchError) {
            NSLog(@"Unable to perform fetch.");
            NSLog(@"%@, %@", fetchError, fetchError.localizedDescription);
        }
    }
}

Create Batch Request

We start by creating an NSEntityDescription instance for the TSPItem entity and use it to initialize a NSBatchUpdateRequest object.

// Create Entity Description
NSEntityDescription *entityDescription = [NSEntityDescription entityForName:@"TSPItem" inManagedObjectContext:self.managedObjectContext];

// Initialize Batch Update Request
NSBatchUpdateRequest *batchUpdateRequest = [[NSBatchUpdateRequest alloc] initWithEntity:entityDescription];

We set the result type of the batch update request to NSUpdatedObjectIDsResultType, which means that the result of the batch update request will be an array containing the object IDs, instances of the NSManagedObjectID class, of the records that were changed by the batch update request.

// Configure Batch Update Request
[batchUpdateRequest setResultType:NSUpdatedObjectIDsResultType];

We also populate the propertiesToUpdate property of the batch update request. For this example, we set propertiesToUpdate to an NSDictionary containing one key, @"done", with value @YES. This simply means that every TSPItem record will be set to done, which is exactly what we want.

// Configure Batch Update Request
[batchUpdateRequest setPropertiesToUpdate:@{ @"done" : @YES }];

Execute Batch Update Request

Even though batch updates bypass the managed object context, executing a batch update request is done by calling executeRequest:error: on a NSManagedObjectContext instance. The first argument is an instance of the NSPersistentStoreRequest class. To execute a batch update, we pass the batch update request we just created. This works fins since the NSBatchUpdateRequest class is a NSPersistentStoreRequest subclass. The second argument is a pointer to an NSError object.

// Execute Batch Request
NSError *batchUpdateRequestError = nil;
NSBatchUpdateResult *batchUpdateResult = (NSBatchUpdateResult *)[self.managedObjectContext executeRequest:batchUpdateRequest error:&batchUpdateRequestError];

Updating the Managed Object Context

As I mentioned earlier, batch updates bypass the managed object context. This gives batch updates their power and speed, but it also means that the managed object context isn't aware of the changes we made. To remedy this issue, we need to do two things:

  • turn the managed objects that were updated by the batch update into faults
  • tell the fetched results controller to perform a fetch to update the user interface

This is what we do in the next few lines of the checkAll: method. We first check if the batch update request was successful by checking the batchUpdateRequestError for nil. If successful, we extract the array of NSManagedObjectID instances from the NSBatchUpdateResult object.

// Extract Object IDs
NSArray *objectIDs = batchUpdateResult.result;

We then iterate over the objectIDs array and ask the managed object context for the corresponding NSManagedObject instance. If the managed object context returns a valid managed object, we turn it into a fault by invoking refreshObject:mergeChanges:, passing in the managed object as the first argument. To force the managed object into a fault, we pass NO as the second argument.

// Extract Object IDs
NSArray *objectIDs = batchUpdateResult.result;

for (NSManagedObjectID *objectID in objectIDs) {
    // Turn Managed Objects into Faults
    NSManagedObject *managedObject = [self.managedObjectContext objectWithID:objectID];
    
    if (managedObject) {
        [self.managedObjectContext refreshObject:managedObject mergeChanges:NO];
    }
}

Fetching Updated Records

The last step is to tell the fetched results controller to perform a fetch to update the user interface. If this is unsuccessful, we log the corresponding error.

// Perform Fetch
NSError *fetchError = nil;
[self.fetchedResultsController performFetch:&fetchError];

if (fetchError) {
    NSLog(@"Unable to perform fetch.");
    NSLog(@"%@, %@", fetchError, fetchError.localizedDescription);
}

While this may seem cumbersome and fairly complex for an easy operation, keep in mind that we bypass the Core Data stack. In other words, we need to take care of some housekeeping that's usually done for us by Core Data.

Step 4: Build & Run

Build the project and run the application in the iOS Simulator or on a physical device. Click or tap the bar button item on the right to check every to-do item in the list.

Conclusion

Batch updates are a great addition to the Core Data framework. Not only does it answer a need developers have had for many years, it isn't difficult to implement as long as you keep a few basic rules in mind. In the next tutorial, we'll take a closer look at asynchronous fetching, another new feature of the Core Data framework.

2014-09-30T16:15:59.000Z2014-09-30T16:15:59.000ZBart Jacobs

Windows Phone 8: Pivot And Panorama

$
0
0

The Windows Phone 8 platform has its own layout styles that make it stand out from any other mobile platform. These unique layouts are possible thanks to a few convenient built-in controls of the Windows Phone 8 SDK. The controls that we're going to be looking at in this tutorial are the Pivot and Panorama controls.

1. Panorama

What is it?

The Windows Phone Panorama layout control offers a unique approach in terms of how content is presented to the user. A Panorama consists of multiple panels or panorama items that each represent a page. At any one time, only one panorama item is visible alongside a small portion of the previous or next panorama item. Using the Panorama control feels like peeking through a keyhole, you can see part of the room behind the door, but not the entire room.

The above screenshot is a great example to demonstrate the Panorama control. The above example contains five panorama items. Each panorama item represent a page with content.

In the above screenshot, the active panorama has a title of menu. At the same time, we can see a glimpse of the next panorama item titled featured. The Panorama control shows the user that more content is waiting to be discovered on the right. Let's find out how to use the Panorama control.

Creating a Panorama Control

Start by creating a new Windows Phone project. To add a Panorama control to the project, choose Add New Item > Windows Phone Panorama Page > Add from the Project menu. This should add a Panorama control with two panorama items. The Panorama control should be visible in Visual Studio's design view.

Creating A New Panorma

Let's add some content to the Panorama control. We're going to populate the first panorama item with a list of colors and the second panorama item with a number of colored rectangles that correspond with the list of colors of the first panorama item. Right now, the Panorama control contains a Grid control with a name of LayoutRoot as shown below.

<Grid x:Name="LayoutRoot"><phone:Panorama Title="my application">    <!--Panorama item one--><phone:PanoramaItem Header="item1"><Grid/></phone:PanoramaItem><!--Panorama item two--><phone:PanoramaItem Header="item2"><Grid/></phone:PanoramaItem>    </phone:Panorama></Grid>

The Grid control named LayoutRoot is the main container of the current page of our application, holding every other element of the page. Remember that in XAML controls are structured in hierarchically, very similar to XML.

The Panorama control is nested in the Grid control and has a Title property of "my application". The Panorama control contains the panorama items. As you can see in the above XAML snippet, the Panorama control currently contains two panorama items. The Header property of the panorama items is item1 and item2 respectively.

The Header property of a panorama item is similar to the Title property of the Panorama control and you can change them to whatever you like.

Adding Colors

Let's now populate the panorama items with some content like we've discussed earlier. Update the content of the two panorama items as shown below.

<!--LayoutRoot contains the root grid where all other page content is placed--><Grid x:Name="LayoutRoot"><phone:Panorama Title="my application">    <!--Panorama item one-->        <phone:PanoramaItem Header="color names">        <StackPanel>        <TextBlock Text="Red" FontSize="30"></TextBlock>        <TextBlock Text="Yellow" FontSize="30"></TextBlock>        <TextBlock Text="Blue" FontSize="30"></TextBlock>        <TextBlock Text="Green" FontSize="30"></TextBlock>        <TextBlock Text="White" FontSize="30"></TextBlock>        </StackPanel>        </phone:PanoramaItem><!--Panorama item two-->    <phone:PanoramaItem Header="colors">    <StackPanel>        <Rectangle Height="50" Fill="Red" Margin="0 0 0 10"></Rectangle>            <Rectangle Height="50" Fill="Yellow" Margin="0 0 0 10"></Rectangle>            <Rectangle Height="50" Fill="Blue" Margin="0 0 0 10"></Rectangle>            <Rectangle Height="50" Fill="Green" Margin="0 0 0 10"></Rectangle>            <Rectangle Height="50" Fill="White" Margin="0 0 0 10"></Rectangle>        </StackPanel>    </phone:PanoramaItem>    </phone:Panorama></Grid>

As you can see I've changed the Header property of the panorama items to color names and colors respectively. To the first panorama item, I've added a StackPanel control containing five TextBlock controls. Each of the TextBlock controls has its Text property set to the name color. I've also set the FontSize property of each TextBlock control to 30px to make the text larger.

The second PanoramaItem control also contains a StackPanel control, containing five Rectangle controls. Each Rectangle control is filled with a color listed in the first panorama item using its Fill property. The Height property of the rectangles is set to 50px and the Margin property is set to 0, 0, 0, 10, which translates to a bottom margin of 10px. You can see the result of your work in the design view of your IDE as shown below.

Panorama View

Now that we've populated the Panorama control with some content, it's time to focus on the second control of this tutorial, the Pivot control.

2. Pivot

What is it?

The Pivot control is another way to present content to the user, unique to the Windows Phone platform. The Pivot control is similar to the Panorama control in some ways, but it has a number of features that set it apart.

Like a Panorama control, a Pivot control can consist of multiple PivotItem controls. Each pivot item can contain other controls, such as Grid and StackPanel controls. The above screenshot shows a Pivot control with two PivotItem controls, directory and facility.

While the Panorama control shows a sneak peek of the next page, the Pivot control does the same for the Header at the top of the Pivot control. This is clearly shown in the above example in which you can see the first letters of the word facility, the title of the second pivot item. To illustrate that the second pivot item is not in focus, its title is greyed out.

Creating a Pivot Control


Let's create a Pivot control by following the same steps we took to create a Panorama control. Instead, select the Windows Phone Pivot Page option. Like the Panorama control, populate the Pivot control with the list of colors and their names as we did earlier. The resulting XAML code for the Pivot control should look similar to what is shown below.

<Grid x:Name="LayoutRoot" Background="Transparent"><!--Pivot Control-->    <phone:Pivot Title="MY APPLICATION">    <!--Pivot item one-->        <phone:PivotItem Header="colour names">            <StackPanel>            <TextBlock Text="Red" FontSize="30"></TextBlock>                <TextBlock Text="Yellow" FontSize="30"></TextBlock>                <TextBlock Text="Blue" FontSize="30"></TextBlock>                <TextBlock Text="Green" FontSize="30"></TextBlock>                <TextBlock Text="White" FontSize="30"></TextBlock>            </StackPanel>            </phone:PivotItem><!--Pivot item two-->        <phone:PivotItem Header="colours">        <StackPanel>            <Rectangle Height="50" Fill="Red" Margin="0 0 0 10"></Rectangle>                <Rectangle Height="50" Fill="Yellow" Margin="0 0 0 10"></Rectangle>                <Rectangle Height="50" Fill="Blue" Margin="0 0 0 10"></Rectangle>                <Rectangle Height="50" Fill="Green" Margin="0 0 0 10"></Rectangle>                <Rectangle Height="50" Fill="White" Margin="0 0 0 10"></Rectangle>                </StackPanel>            </phone:PivotItem>    </phone:Pivot></Grid>

Before we can build and run the application to see both controls in action, we need to implement a way to navigate the application's pages. That will be the focus of the next section.

3. Page Navigation

If you run the application in its current form, you will see the MainPage.xaml page, the default entry point for every Windows Phone application. Let's change this.

Adding Buttons

To navigate to the Panorama and Pivot control we implemented earlier, we need to add two Button controls to the MainPage.xaml page. Double-click MainPage.xaml in your IDE and drag two Button controls from the Toolbox to the page in Visual Studio's design view.

As you can see below, I've also changed the Content properties of the Button controls to read Panorama and Pivot.

Editing Pivot And Panorama Text

Implementing the Button Controls

When the use taps a Button control, we want the application to navigate to either the Panorama or the Pivot control. Let's start with the left button first.

Panorama

Start by double-clicking the left Button control in the design view. This should take you to MainPage.cs, which contains the class that is linked to MainPage.xaml. Visual Studio has already created a method for us, Button_Click, which is invoked when the user taps the button labeled Panorama.

private void Button_Click(object sender, RoutedEventArgs e) {}

When the user taps the first button, the application should take them to the Panorama control. We accomplish this by updating the Button_Click method as shown below.

private void Button_Click(object sender, RoutedEventArgs e) {
  NavigationService.Navigate(new Uri("/PanoramaPage1.xaml", UriKind.Relative));
}

We invoke the Navigate method on NavigationService, passing in the destination, a Uri instance, and the type of destination, UriKind.Relative. Note that the name of the destination page needs to match the first page of the Panorama control, PanoramaPage1.xaml in the above example. Don't forget the leading forward slash.

Pivot

Navigating to the Pivot control is very similar. Open MainPage.xaml, double-click the Button control labeled Pivot, and implement the event handler, Button_Click_1, as shown below. The only difference is the destination we navigate to, PivotPage1.xaml.

private void Button_Click_1(object sender, RoutedEventArgs e) {
  NavigationService.Navigate(new Uri("/PivotPage1.xaml", UriKind.Relative));
}

Build and run the application to test the buttons as well as the Panorama and Pivot controls. Use the physical back button of your device or emulator to navigate back to the previous page.

Conclusion

In this tutorial, we've covered two important layout controls of the Windows Phone platform, the Panorama and Pivot controls. We also revisited navigation and used some of the common controls on Windows Phone, such as Button, TextBox, and Rectangle controls. In the next article, we will conclude this introductory series on Windows Phone and look ahead at what's next for you.

2014-10-01T17:00:30.000Z2014-10-01T17:00:30.000ZSani Yusuf
Viewing all 1836 articles
Browse latest View live