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

Introducing Vue and Weex for Native Mobile Apps

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

Vue is a popular JavaScript framework for web apps with easy binding between data in memory and the user interface. Now Weex allows us to code native mobile apps using the Vue framework!

Why do we use Vue and other data binding frameworks like Angular and React? What's so special about them?  We use them to ensure that application data which is stored in memory stays in sync with the user interface and vice versa. 

We also use these frameworks to enable us to build applications very quickly, and in a way that is optimized for performance.

In this tutorial I'll show you how to use the Vue framework, in particular how to understand its concepts of data binding and templates. Then, I'll go on to introduce the Weex platform, for coding native mobile apps using Vue!

Data Binding

Let's look at a simple example to understand how these frameworks can actually save us time. What we want is a simple input field that stays in sync with our application data. Our app itself can change the data programmatically, and the user can change it via user input, so we need to be watching both the UI and application data.

Two way data binding

Writing code that would support this data binding would be verbose. We would need to create event listeners and proxy objects and observables to capture any changes in the application data. And these complexities just grow and grow as more types of data and inputs are added. Vue and other data binding frameworks prevent us having to write all of that binding code. 

With Vue, if our user changes some input data, it will sync back to the application data like so:

Changes flowing from the UI to the model

Or if the application changes the data, it will update the user interface like this:

Changes flowing from the model to the UI

When we keep the user interface and the app data together in sync, it means our app does exactly what we expect it to do. Vue will manage all of this and allow other powerful data binding processes to occur.

Getting Set Up

Now that we know why we use these frameworks, let's set up a simple Vue application to run some examples. Create a new HTML file anywhere on your computer and paste the following code into it:

This is a simple HTML file that links to the Vue JS library. It contains a div element with the ID of app. Inside the script tags we have a variable called app that we use to point to our view—I'll explain this part later.

Then we create a new Vue instance, or "view". This constructor tells the framework which element will contain our application UI and keep it in sync with the application data. 

Now double click on the HTML file to open it in the browser, and open the browser console window.

The browser console in Chrome

Text Interpolation

Text interpolation lets us embed expressions in our HTML code that will be interpreted when the page is rendered. The expressions are live, so if the data they depend on is changed, the page will be updated in real time. This is known as declarative rendering, which allows us to place expressions anywhere within an element's content. Let's review with a simple example.

JS

Our JavaScript code now contains a data object that will store all of our application data for this view. Within it, I've created the message property with the string "Hello world"

Next, let's display this property in the HTML.

HTML

The expressions are indicated with double braces syntax. Vue JS manages the dependencies of each expression and updates the page live if they change. In our case, we have two expressions, with the message property as a dependency of each one. The first expression {{ message }} just displays the message property. The second {{ message.split('').reverse().join('') }} expression takes the message property, and then:

  • Splits the string into an array:
    [ "h","e","l","l","o"," ","w","o","r","l","d" ]
  • Reverses the order of the array:
    [ "d","l","r","o","w"," ","o","l","l","e","h" ]
  • Joins the array together to get "dlrow olleh", which is the same message but printed backwards.

Now open the browser and refresh the HTML page. Then open the browser's console window and assign app.message a new value and see how the output is updated in the browser.

Simple Vue template example

You can also use math in template expressions, or structured data in objects. Actually, as you might have guessed, Vue expressions are just JavaScript. Access to global variables is sandboxed, though, so you can access Math, but not window. This helps keep your apps safe—and your users too. 

By using Vue with just a few lines of code, we can have advanced two-way data binding. This ensures that the user interface and the application data are in sync with relative ease. 

Directives

Directives are another way of binding data in our views. We can use them to bind application data to attributes, events, input fields, and repeatable data. Let's go through each directive and discover how they work.

  • v-bind: bind an attribute value
  • v-model: bind app data to an input element like a textarea
  • v-on: define an event handler
  • v-for: bind to an array or object

v-bind Directive

The v-bind directive is used for attribute data binding. It allows us to bind application data to an attribute's value. Think of it like text interpolation but within an attribute. You can bind classidvalue or any other attribute with the v-bind directive. 

For this example, I would like to bind our application data to the data-attr attribute using the v-bind directive v-bind:data-attr.

JS

HTML

In the example above, we bound an attribute called data-attr to a series of different data sources. First, we bound it to the type and names properties of object. Then we bound it to a math expression, and then joined all the bindings together into a single array attribute.

Take a look at the output in the browser: you can click on the Elements tab to see the output of each attribute's value.

Binding attribute values

Again, you can change the application data in the console to see the data binding process.

Changes to the model are rendered automatically

Think of the v-bind directive as allowing expressions in attribute values. This is incredibly powerful and easy to establish with the Vue library.

v-model Directive

This directive is used specifically to keep the application data in sync with input fields, text areas, and selection elements. Here's an example:

JS

HTML

For the first section of this page, we have a text input field and text area, both of which have the v-model directive that keeps these input fields in sync with the message property, using v-model="message". That way, if you change either one, the model will be updated and then the other input field will be updated. Go ahead and try it out!

Binding to input elements

In the next section we have a drop-down synced to the selected property with  v-model="selected". That way, if the selection is changed, our model will be updated.

Finally, we have a multiple selection. I've shown how to do this in two ways: with multiple checkboxes and with a multiple select input. As we can have multiple values, I've created the checkedNames array that can store multiple values. The multiple select input and the checkboxes each have a v-model directive targeting the checkNames property. Give it a try, and they should stay in sync as you make selections.

Multiple selection binding

The v-on Directive

This directive allows us to attach events to HTML elements. This directive can be used on certain elements that can have input events attached to them like hovering, clicks, text input, key presses, and more. For this example, we'll create a simple button with a click event.

JS

HTML

In the v-on directive, after the colon, we specify the event we want to attach. In this example, when the click event is fired, we'll run some expressions. First, we open an alert dialog box, and then we change the value of the clicked property. Note that you can call functions in v-on expressions.

A button with a click event

v-for Directive

This directive is one of the most powerful of them all. We can watch any object or array for changes and render repeatedly a part of our template code for each property or element found in that object or array. For example, to render an array of names as a list:

JS

HTML

In this example, we first attach the v-for directive onto the element that you want to repeat. The value of the directive specifies the object or array we want to iterate over (names) as well as a variable that will contain the value for each iteration (name). Now, within this repeated element, we can use the name variable in expressions.

If we then modify the array, for example with a method like push, sort or reverse, the template data will automatically be updated. Try running the example and modify the array in the console window.

Rendering a list of elements with the v-for directive

Components

The data binding process happens in views. Components are just reusable views that we can repeat throughout our application. Each component must have some template data to be rendered as part of the user interface and some application data. You can optionally include some styling if you want.

Let's use the v-for directive again to output list items. But this time, we'll make each item a component. We'll give this component a name so that we can target it within our template code: list-item. Components can also have "registered properties", to which we can assign a value to be assigned when we create the component. In my case, the list-item component will expect to receive a value for the name property, defined with props:["name"]

Let's now create this component. Please add the following code into your script tags:

JS

Also make sure you have the following application data:

HTML

Here you can see the list-item component will be repeated for each name found in the array. Each name will be assigned to the name variable which is defined in the v-for directive. We're passing the name property to the component using v-bind.

Each instance is just a copy of the component. We can modify each copy or instance independently of one another. So think of components as the blueprint and the instances as copies made from the blueprint. Here is the end result:

List rendered with components

Compilation and the Vue CLI

We've been working with a very simple HTML file and letting Vue interpret everything at run-time. However, Vue does come with a command-line tool. You may be asking yourself why. One reason is that pre-compiled page templates will perform better than templates that Vue interprets at run-time. Another reason is that, if we were to build a large-scale application and try to fit it into one HTML file, it would quickly become unmanageable. 

So we need modularity to break down a large application into smaller pieces. 

Installing the Vue CLI

To use the command line, you'll need to open up the console window for your operating system.

  • For Mac, press Command-Space and then type terminal and hit Return.
  • For Windows, search for the command prompt in the startup menu, make sure to right click and "open as administrator".
  • For Linux, press Control-Alt-T.

Before proceeding, make sure you have the latest version of Node.js installed. Then we need to install Webpack, which will compress our project's file size, making it faster in our browser. Then we can install the Vue CLI and run the relevant commands for your platform:

Mac & Linux

  • sudo npm install -g webpack
  • sudo npm install -g vue-cli

Windows (make sure you run the console as administrator)

  • npm install -g webpack
  • npm install -g vue-cli

That's it! We're now ready to start setting up our advanced Webpack project. Firstly, navigate to the directory where we want to create our project, in my case the desktop, and then create the project. You can replace myapp with any project name you'd like.

  • vue init webpack myapp

You will be led through a series of questions about your project, prompting you to fill in data like title and description and asking you whether to install third-party plugins. For this example, you can answer no to all of the optional extras. Once it's created, we need to install the dependencies, so navigate to the project directory, and we'll run the install command.

  • cd myapp
  • npm install

Let NPM install all the dependency packages, and then we're ready to carry on. 

Creating a Vue Project

Once the packages have been installed, we can then run the development server by typing npm run dev. Your browser window should open, displaying the following page.

The Vue starter project welcome screen

We won't go through the structure of the entire project, but when you open up the myapp directory you will see the src directory. It contains an App.vue file, a main.js file and, in the components directory, the Hello.vue file.

The Vue files are components. The main.js file configures the initial view and potentially other configurations as well. Let's take a look at the App.vue and Hello.vue files.

The vue files from the Vue starter project

Here you can see each Vue component is broken down into three parts:

  • <template>: the HTML markup that makes up part of the UI.
  • <script>: application data, filters, methods, computed properties, watchers, and methods.
  • <style>: the CSS or Sass styling of our components.

Compilation

Compiling all the components together will produce a large-scale application. This means when we're developing, we work on small modular pieces of code, called components, instead of the entire application. In Vue we have single-file components that contain the JavaScript, HTML, and CSS. It'll even take care of transpiling ES6 to ES5, Sass to CSS and Jade to HTML if you choose to use those languages.

You'll notice in the App.vue file, I've highlighted where it imports the Hello.vue component. Components can be nested inside other components! 

When compiling, our project is built with the following process:

Vue build process

We're still using the same syntax as in the earlier examples. However, we are now working with smaller Vue files and compiling them together. We also have some more advanced features like the preprocessors and Jade, Sass, ES6 and Webpack compression.

Weex

Now that we understand the Vue library, let's take a quick look to see how we can take our web app and turn it into a native mobile app, installable on iOS or Android. 

Weex is a hybrid framework, meaning it allows multiple technologies, just as a hybrid car can use both electric and petrol. In our case, we use JavaScript code from our web app, but we render to a native user interface. Also, from JavaScript we can access the device's native APIs to access hardware like the camera, sensors, and file system.

Parts of a Weex app

With Weex, instead of rendering our application to HTML, we use XML. Actually, HTML and XML are very similar, so the syntax will look familiar. This XML will then be converted to native components. Now our JavaScript will be able to talk to those native components just like it talks to the DOM in Vue with HTML. Not only that, but native components can be styled and positioned with CSS including animations, transitions and more, and they can be integrated to the native layer.

That's just a teaser of what Weex can do. In the next tutorials, I'll take you more in depth with Weex, and we'll see how to build some practical cross-platform native apps.

Pros

Vue has a simple syntax and is increasing in popularity very quickly. Weex allows us to build mobile apps using JavaScript and Vue, but still deliver a native app experience. 

Cons

Vue itself is stable, but Weex is still in early development—it currently resides in the Apache incubator. But don't worry, Weex will be production ready soon, and it's backed by the tech giant Alibaba. So, if building on a developer preview concerns you, you might wait until Weex reaches full release. 

Conclusion

You've now seen how data binding is a key reason for using Vue and similar frameworks. They save us development time and provide a standard way to build applications. You've also seen how to use text interpolation, directives, and events in Vue, and how these features work together to keep app data in sync with the user interface.

We started out with a basic project with only one view. But then we created a more advanced project that had smaller, more modular views called components. Components let us break our project down so it is easier to code and maintain. After, we saw how to use the Vue compiler to allow transpilation of ES6, Jade and Sass into the standard languages, while compressing file sizes to the minimum.

All of this knowledge will help you when you start coding with Weex. Weex will allow us to take our Vue web app and turn it into a mobile app. Weex is a bit different—we use XML with special components, instead of HTML—but we can still use other web technologies, like CSS and JavaScript. That means we don't have to change our application logic from web app to mobile app.

Stay tuned for my next post on Weex development, and in the meantime, check out some of our other posts on mobile app development with web technologies.

2017-05-10T18:00:00.000Z2017-05-10T18:00:00.000ZLawrence Turton

SpriteKit Basics: Nodes

$
0
0

SpriteKit is Apple's 2D game engine—a rendering engine built on top of OpenGL. It was introduced with iOS 7, and each subsequent release has brought great additions to the framework. With the use of textured sprites, a built-in physics engine, and the very powerful SKAction class, you can very quickly build functional 2D games.

SpriteKit has built-in editors for scenes and particles, a camera node since the release of iOS9, and built-in support for tilesets since the release of iOS 10. With these new additions, SpriteKit is quickly becoming a powerhouse for creating 2D games.

To follow along with this tutorial, just download the accompanying GitHub repo. It has a folder called ExampleProject Starter. Open the project in that folder in Xcode, and you're ready to go!

Nodes

Nodes are the fundamental building blocks of SpriteKit, and SKNode is the base class of all nodes. All of your onscreen assets will be an SKNode or a subclass thereof. SKNodes by themselves do not provide any visual content, however. All visual content is drawn using one of a number of predefined SKNode subclasses. SKNodes and its subclasses share several properties you can alter. Some of the more important ones are as follows.

  • position (CGPoint): the node's position within its parent's coordinate system
  • xScale (CGFloat): scales the width of a node by a multiplier
  • yScale(CGFloat): scales the height of a node by a multiplier
  • alpha (CGFloat): the transparency of the node
  • zRotation (CGFloat): the Euler rotation about the z axis (in radians)

One of the most important SKNodes is the SKScene. This is the root node to which all other nodes are added. By itself, SKScene does not provide any visual elements, but it displays the nodes which are added to it.

Scene Nodes

SKScenes are the root nodes to which all other nodes are added. The scene animates and renders the content from its child nodes. To display a scene, you add it to an SKView (which is a subclass of UIView and therefore has many of the same properties as UIView).

In the SpriteKit starter project, the initial scene is showing when the project loads. For now, this is just a blank black screen. It is shown when the GameViewController invokes presentScene(_:) on the view instance, passing in the scene as a parameter:

Don't worry about the other options for now; I'll explain them later in this series.

Creating a Scene

Many games have more than one screen or scene, so we will create a new scene from scratch and then show it from our initial scene.

Select File> New> File from Xcode's menu, and choose Cocoa Touch Class.

Choose the Cocoa Touch Class template

Make sure Class is set to NewScene and that Subclass of is set to SKScene. Press Next and then Create, making sure the main target is checked. Below is the code for the NewScene.swift.

Now we have two scenes in our project, and neither has any visual content. Let's add an SKLabelNode (like all nodes, this is a subclass of SKNode). The SKLabelNode's sole purpose is to display a text label.

Label Nodes

Label nodes, implemented in the SKLabelNode class, are used to show text within your game. You can use custom fonts if you wish, but for our purposes we will just stick to the default, which displays white text and is set to Helvetica Neue Ultra Light, 32 point.

Add the following inside the didMove(to:) method within GameScene.swift. This method is called immediately after a scene is presented by a view. Generally, this is where you would set up any of your game's assets and add them to the scene.

Here we create an SKLabelNode using the convenience initializer init(text:), which takes as a parameter a string of text.

Adding and Removing Nodes

Just initializing nodes will not show them in the scene. To get the nodes to show, you have to invoke the addChild(_:) method on the receiving node, passing the SKNode that you wish to add as a parameter.

Add the following within the didMove(to:) method.

The addChild(_:) method is not exclusive to SKScenes, but is a method of SKNode. This allows you to build a complex hierarchy of nodes—known as the "node tree". For example, suppose you have a game character and you wanted to move its arms and legs separately. You could create an SKNode instance and then add each individual part as a child of that SKNode (the containing node is known as the parent node). This would give you the benefit of being able to move the character as a whole unit by moving the parent SKNode, but also allow you to move each individual part individually.

Another important method for adding nodes is the insertChild(_:at:) method, which inserts a child into a specific position within the receiver node's list of children. When you add a child to a node, the node maintains an ordered list of children which is referenced by reading the node's children property. It is important when adding multiple nodes to a parent node to take this into consideration, as the order in which you add the nodes affects some of the aspects of scene processing, including hit testing and rendering.

To remove a node, you invoke the removeFromParent() method on the node you wish to remove.

Now that we have covered adding and removing nodes, we can move our focus back to the example project. If you recall, we had just added an SKLabelNode to the GameScene. If you test now, you will see just half of the text off to the bottom left of the screen.

Test showing blank screen with text half off to the bottom left of the screen

Why is only half the text showing, though? Now would be a good time to talk about SpriteKit's coordinate and positioning system.

Positioning and Coordinates

By default, SpriteKit's coordinate system places (0,0) at the bottom left of the screen. Also by default, SpriteKit places nodes so they are positioned at (0,0). Still, though... why are we only seeing half of the text? This is because by default the text label is centered horizontally on the label node's origin, which is (0,0). Below is an image that shows how a node's coordinate system works.

A nodes x and y coordinates

Node's origins are at (0,0), and a positive x coordinate moves to the right and a positive y coordinate goes up the screen. Remember that an SKScene is a node, and therefore its origin is also (0,0).

Setting a Node's Position

Now that we have learned SpriteKit's coordinate system works and how it places nodes, we can move the SKLabelNode to a different position so we can see all of the text. Add the following to the didMove(to:) method within GameScene.swift.

Here we position the label to the center of the scene. The position property is of type CGPoint, which has x and y values that represent a single point within the scene.

If you test now, you should see the label has been positioned in the center of the scene.

Test with label positioned in centre of screen

Switching Between Scenes

As it currently stands, NewScene is just a blank scene. Let's also add a label to it, and then we can learn how to switch between scenes. Here's a challenge: before you read ahead, try to add a label to NewScene that says, "Go Back". My solution is below.

The first thing we need to do is add the didMove(to:) method. Add the following to NewScene.swift.

Next, we need to add the label. Add the following within the didMove(to:) method that you added above.

This adds a label to  NewScene with the text "Go Back". Next, we'll implement the functionality this label suggests—we'll respond to touch events by switching scenes.

Responding to Touch

Nearly all mobile games will be interacted with using touch. In this step, you will learn how to respond to touch events within your game.

To register touch event handlers within your game, you must implement the view's touchesBegan(_:with:) method. Add the following to GameScene.swift:

If you want to test this now, you will see YOU TOUCHED printed to the console when you touch on the screen. What we usually need, however, is to be able to tell when a specific node has been touched. To do this, we need some way to find and identify the nodes. We will learn how to accomplish this, and then come back and finish the touchesBegan(_:with:) method.

Searching the Node Tree

To be able to identify a node, you use the node's name property and the search the node tree for a node with that name. The node's name property takes an alphanumeric string without any punctuation. 

There are a couple of methods to search for a node by its name property. If you already have a reference to the node, you can just check its name property directly, which is what we will do in the touchesBegan(_:with:) method. However, it is important to know how to search the node tree for a particular node by name, or to search for a group of nodes with the same name.

The childNode(withName:) method searches the children of a node for the specific name passed in as a parameter.

The enumerateChildNodes(withName:using:) method searches a node's children and calls the block once for each matching node it finds. You use this method when you want to find all nodes that share the same name.

The subscript(_:) method returns an array of nodes that match the name parameter.

You can also search for nodes using an advanced searching syntax that allows you to search the entire scene tree, or search for a pattern rather than an exact name, for example. This advanced searching capability is beyond the scope of this tutorial. However, if you wish to learn more, you can read about in the SKNode programming reference.

Now that we know how to search for nodes within the node tree, let's give our labels a name.

Add the following within the didMove(to:) method within GameScene.swift.

Here, we set startGameLabel's name property to startgame.

We also need to set the label's name within NewScene. Add the following with the didMove(to:) method within NewScene.swift.

We set the name property to goback.

Detecting Which Node Is Touched

Add the following within the touchesBegan(_:with:) method within GameScene.swift.

The multiTouchEnabled property of the scene's view is set to false by default, which means the view only receives the first touch of a multitouch sequence. With this property disabled, you can retrieve the touch by using the first computed property of the touches set, since there is only one object in the set.

We can get the touchLocation within the scene from the location property of the touch. We can then figure out which node was touched by invoking atPoint(_:) and passing in the touchLocation.

We check if the touchedNode's name property is equal to "startgame", and if it is, we know that the user has touched the label. We then create an instance of NewScene and set its scalemode property to be the same as the current scene—this ensures the scene acts the same across different devices. Finally, we create an SKTransition and invoke the presentScene(_:transition:) method, which will present the scene along with the transition.

The SKTransition class has many class methods that you can invoke to show different transitions between scenes instead of immediately showing the scene. This provides a bit of "eye candy" for the end user, and makes showing a new scene seem less abrupt. To see all of the available transition types, check out the SKTransition class in the reference guide.

I'm not going to implement the touchesBegan(_:with:) method in NewScene. Why don't you try doing that on your own and have the label transition back to the GameScene using a different transition type? The code will closely resemble what we have above, only remember we named the SKLabelNode"goback".

Conclusion

We have learned a good bit about nodes so far using scenes, and you've seen how to use a label node as a generic example to learn some of the characteristics of nodes. We've studied their coordinate systems, how to locate them within the node tree, how to position them, and how to respond to touch events. 

There are several other kinds of nodes available, and we'll take a look at them in the next tutorial—starting with SKSpriteNode!

To learn more about how to get started with SpriteKit, you should also check out Davis Allie's post here on Envato Tuts+.

Also, check out our SpriteKit courses! These will take you through all the steps of building your first SpriteKit game for iOS, even if you've never coded with SpriteKit before.

2017-05-16T15:00:00.000Z2017-05-16T15:00:00.000ZJames Tyner

SpriteKit Basics: Nodes

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

SpriteKit is Apple's 2D game engine—a rendering engine built on top of OpenGL. It was introduced with iOS 7, and each subsequent release has brought great additions to the framework. With the use of textured sprites, a built-in physics engine, and the very powerful SKAction class, you can very quickly build functional 2D games.

SpriteKit has built-in editors for scenes and particles, a camera node since the release of iOS9, and built-in support for tilesets since the release of iOS 10. With these new additions, SpriteKit is quickly becoming a powerhouse for creating 2D games.

To follow along with this tutorial, just download the accompanying GitHub repo. It has a folder called ExampleProject Starter. Open the project in that folder in Xcode, and you're ready to go!

Nodes

Nodes are the fundamental building blocks of SpriteKit, and SKNode is the base class of all nodes. All of your onscreen assets will be an SKNode or a subclass thereof. SKNodes by themselves do not provide any visual content, however. All visual content is drawn using one of a number of predefined SKNode subclasses. SKNodes and its subclasses share several properties you can alter. Some of the more important ones are as follows.

  • position (CGPoint): the node's position within its parent's coordinate system
  • xScale (CGFloat): scales the width of a node by a multiplier
  • yScale(CGFloat): scales the height of a node by a multiplier
  • alpha (CGFloat): the transparency of the node
  • zRotation (CGFloat): the Euler rotation about the z axis (in radians)

One of the most important SKNodes is the SKScene. This is the root node to which all other nodes are added. By itself, SKScene does not provide any visual elements, but it displays the nodes which are added to it.

Scene Nodes

SKScenes are the root nodes to which all other nodes are added. The scene animates and renders the content from its child nodes. To display a scene, you add it to an SKView (which is a subclass of UIView and therefore has many of the same properties as UIView).

In the SpriteKit starter project, the initial scene is showing when the project loads. For now, this is just a blank black screen. It is shown when the GameViewController invokes presentScene(_:) on the view instance, passing in the scene as a parameter:

Don't worry about the other options for now; I'll explain them later in this series.

Creating a Scene

Many games have more than one screen or scene, so we will create a new scene from scratch and then show it from our initial scene.

Select File> New> File from Xcode's menu, and choose Cocoa Touch Class.

Choose the Cocoa Touch Class template

Make sure Class is set to NewScene and that Subclass of is set to SKScene. Press Next and then Create, making sure the main target is checked. Below is the code for the NewScene.swift.

Now we have two scenes in our project, and neither has any visual content. Let's add an SKLabelNode (like all nodes, this is a subclass of SKNode). The SKLabelNode's sole purpose is to display a text label.

Label Nodes

Label nodes, implemented in the SKLabelNode class, are used to show text within your game. You can use custom fonts if you wish, but for our purposes we will just stick to the default, which displays white text and is set to Helvetica Neue Ultra Light, 32 point.

Add the following inside the didMove(to:) method within GameScene.swift. This method is called immediately after a scene is presented by a view. Generally, this is where you would set up any of your game's assets and add them to the scene.

Here we create an SKLabelNode using the convenience initializer init(text:), which takes as a parameter a string of text.

Adding and Removing Nodes

Just initializing nodes will not show them in the scene. To get the nodes to show, you have to invoke the addChild(_:) method on the receiving node, passing the SKNode that you wish to add as a parameter.

Add the following within the didMove(to:) method.

The addChild(_:) method is not exclusive to SKScenes, but is a method of SKNode. This allows you to build a complex hierarchy of nodes—known as the "node tree". For example, suppose you have a game character and you wanted to move its arms and legs separately. You could create an SKNode instance and then add each individual part as a child of that SKNode (the containing node is known as the parent node). This would give you the benefit of being able to move the character as a whole unit by moving the parent SKNode, but also allow you to move each individual part individually.

Another important method for adding nodes is the insertChild(_:at:) method, which inserts a child into a specific position within the receiver node's list of children. When you add a child to a node, the node maintains an ordered list of children which is referenced by reading the node's children property. It is important when adding multiple nodes to a parent node to take this into consideration, as the order in which you add the nodes affects some of the aspects of scene processing, including hit testing and rendering.

To remove a node, you invoke the removeFromParent() method on the node you wish to remove.

Now that we have covered adding and removing nodes, we can move our focus back to the example project. If you recall, we had just added an SKLabelNode to the GameScene. If you test now, you will see just half of the text off to the bottom left of the screen.

Test showing blank screen with text half off to the bottom left of the screen

Why is only half the text showing, though? Now would be a good time to talk about SpriteKit's coordinate and positioning system.

Positioning and Coordinates

By default, SpriteKit's coordinate system places (0,0) at the bottom left of the screen. Also by default, SpriteKit places nodes so they are positioned at (0,0). Still, though... why are we only seeing half of the text? This is because by default the text label is centered horizontally on the label node's origin, which is (0,0). Below is an image that shows how a node's coordinate system works.

A nodes x and y coordinates

Node's origins are at (0,0), and a positive x coordinate moves to the right and a positive y coordinate goes up the screen. Remember that an SKScene is a node, and therefore its origin is also (0,0).

Setting a Node's Position

Now that we have learned SpriteKit's coordinate system works and how it places nodes, we can move the SKLabelNode to a different position so we can see all of the text. Add the following to the didMove(to:) method within GameScene.swift.

Here we position the label to the center of the scene. The position property is of type CGPoint, which has x and y values that represent a single point within the scene.

If you test now, you should see the label has been positioned in the center of the scene.

Test with label positioned in centre of screen

Switching Between Scenes

As it currently stands, NewScene is just a blank scene. Let's also add a label to it, and then we can learn how to switch between scenes. Here's a challenge: before you read ahead, try to add a label to NewScene that says, "Go Back". My solution is below.

The first thing we need to do is add the didMove(to:) method. Add the following to NewScene.swift.

Next, we need to add the label. Add the following within the didMove(to:) method that you added above.

This adds a label to  NewScene with the text "Go Back". Next, we'll implement the functionality this label suggests—we'll respond to touch events by switching scenes.

Responding to Touch

Nearly all mobile games will be interacted with using touch. In this step, you will learn how to respond to touch events within your game.

To register touch event handlers within your game, you must implement the view's touchesBegan(_:with:) method. Add the following to GameScene.swift:

If you want to test this now, you will see YOU TOUCHED printed to the console when you touch on the screen. What we usually need, however, is to be able to tell when a specific node has been touched. To do this, we need some way to find and identify the nodes. We will learn how to accomplish this, and then come back and finish the touchesBegan(_:with:) method.

Searching the Node Tree

To be able to identify a node, you use the node's name property and the search the node tree for a node with that name. The node's name property takes an alphanumeric string without any punctuation. 

There are a couple of methods to search for a node by its name property. If you already have a reference to the node, you can just check its name property directly, which is what we will do in the touchesBegan(_:with:) method. However, it is important to know how to search the node tree for a particular node by name, or to search for a group of nodes with the same name.

The childNode(withName:) method searches the children of a node for the specific name passed in as a parameter.

The enumerateChildNodes(withName:using:) method searches a node's children and calls the block once for each matching node it finds. You use this method when you want to find all nodes that share the same name.

The subscript(_:) method returns an array of nodes that match the name parameter.

You can also search for nodes using an advanced searching syntax that allows you to search the entire scene tree, or search for a pattern rather than an exact name, for example. This advanced searching capability is beyond the scope of this tutorial. However, if you wish to learn more, you can read about in the SKNode programming reference.

Now that we know how to search for nodes within the node tree, let's give our labels a name.

Add the following within the didMove(to:) method within GameScene.swift.

Here, we set startGameLabel's name property to startgame.

We also need to set the label's name within NewScene. Add the following with the didMove(to:) method within NewScene.swift.

We set the name property to goback.

Detecting Which Node Is Touched

Add the following within the touchesBegan(_:with:) method within GameScene.swift.

The multiTouchEnabled property of the scene's view is set to false by default, which means the view only receives the first touch of a multitouch sequence. With this property disabled, you can retrieve the touch by using the first computed property of the touches set, since there is only one object in the set.

We can get the touchLocation within the scene from the location property of the touch. We can then figure out which node was touched by invoking atPoint(_:) and passing in the touchLocation.

We check if the touchedNode's name property is equal to "startgame", and if it is, we know that the user has touched the label. We then create an instance of NewScene and set its scalemode property to be the same as the current scene—this ensures the scene acts the same across different devices. Finally, we create an SKTransition and invoke the presentScene(_:transition:) method, which will present the scene along with the transition.

The SKTransition class has many class methods that you can invoke to show different transitions between scenes instead of immediately showing the scene. This provides a bit of "eye candy" for the end user, and makes showing a new scene seem less abrupt. To see all of the available transition types, check out the SKTransition class in the reference guide.

I'm not going to implement the touchesBegan(_:with:) method in NewScene. Why don't you try doing that on your own and have the label transition back to the GameScene using a different transition type? The code will closely resemble what we have above, only remember we named the SKLabelNode"goback".

Conclusion

We have learned a good bit about nodes so far using scenes, and you've seen how to use a label node as a generic example to learn some of the characteristics of nodes. We've studied their coordinate systems, how to locate them within the node tree, how to position them, and how to respond to touch events. 

There are several other kinds of nodes available, and we'll take a look at them in the next tutorial—starting with SKSpriteNode!

To learn more about how to get started with SpriteKit, you should also check out Davis Allie's post here on Envato Tuts+.

Also, check out our SpriteKit courses! These will take you through all the steps of building your first SpriteKit game for iOS, even if you've never coded with SpriteKit before.

2017-05-16T15:00:00.000Z2017-05-16T15:00:00.000ZJames Tyner

Quick Tip: Enumerations in Swift

$
0
0

Enumerations are a common design pattern in many programming languages. While you may be familiar with enumerations in C and Objective-C, Swift's implementation of enumerations is significantly more powerful and flexible. In this quick tip, you'll learn what's special about enumerations in Swift, how to use them in your projects, and what makes them so powerful.

1. What Is an Enumeration?

Enumerations aren't new and they're certainly not unique to Swift. However, if you're familiar with enumerations in C, then you're going to love Swift's powerful take on enumerations.

If enums or enumerations are new to you, then you may not be familiar with what they have to offer. In Swift, enumerations are first class types that define a list of possible values for that type.

An example might be the possible states of a network connection. The possible states could be:

  • disconnected
  • connecting
  • connected

We could add a fourth state for the case the state is unknown. With this example in mind, let's see how to define and implement such an enumeration.

Basics

Like I said, enumerations are first class types in Swift. An enumeration definition looks very similar to a class or structure definition. In the example below, we define the ConnectionState enumeration.

The name of the enumeration is preceded by the enum keyword and followed by a pair of curly braces. The ConnectionState enumeration will define the possible states of a network connection. To define these states, we add member values or members to the enumeration's definition. The definition of a member value always starts with the case keyword.

In C or Objective-C, the above enumeration would look a bit different as illustrated in the example below. Each value of the enumeration corresponds with an integer, for example, ConnectionStateUnknown equals 0, ConnectionStateDisconnected equals 1, etc.

This isn't true in Swift. The members of an enumeration don't automatically correspond with an integer value. The members of the ConnectionState enumeration are values themselves and they are of type ConnectionState. This makes working with enumerations safer and more explicit.

Raw Values

It is possible to explicitly specify the values of the members of an enumeration. In the following example, the members of the ConnectionState enumeration have a raw value of type Int. Each member is assigned a raw value, corresponding with an integer.

Note that we specify the type of the raw values in the enumeration's definition and that no two member values can have the same raw value. If we only specify a value for the Unknown member, then Swift will automatically increment the value of the Unknown member and assign unique values to the other members of the enumeration. To better illustrate this, the below example is identical to the previous definition of the ConnectionState enumeration.

2. Working with Enumerations

Initialization

Using the ConnectionState enumeration is similar to using any other type in Swift. In the next example, we declare a variable, connectionState, and set its value to ConnectionState.Connecting.

The value of connectionState is ConnectionState.Connecting and the variable is of type ConnectionState.

Swift's type inference is very convenient when working with enumerations. Because we declared connectionState as being of type ConnectionState, we can now assign a new value by using the shorthand dot syntax for enumerations.

Control Flow

Using enumerations in an if or switch statement is straightforward. Remember that switch statements need to be exhaustive. Add a default case if necessary.

The following example demonstrates how the ConnectionState enum can be used. It also shows how to access the associated value of an enum member. The canConnect function accepts a ConnectionState instance and returns a Bool.

The canConnect function only returns true if the ConnectionState instance passed to the function is equal to .Connected and its associated value is an Int equal to 3000. Note that the associated value of the Connected member is available in the switch statement as a constant named port, which we can then use in the corresponding case.

3. Associated Values

Another compelling feature of Swift enums are associated values. Each member of an enum can have an associated value. Associated values are very flexible. For example, associated values of different members of the same enum don't need to be of the same type. Take a look at the following example to better understand the concept of associated values.

The Unknown and Disconnected members don't have an associated value. TheConnecting member has an associated value of type (Int, Double), specifying the port number and timeout interval of the connection. The Connected member has an associated value of type Int, specifying the port number.

It's important to understand that an associated value is linked to or associated with a member of the enumeration. The member's value remains unchanged. The next example illustrates how to create a ConnectionState instance with an associated value.

4. Methods and Value Types

Methods

Enumerations are pretty powerful in Swift. Enumerations can even define methods, such as an initializer to select a default member value if none was specified.

In this example, we initialize an instance of the ConnectionState enumeration without explicitly specifying a value for it. In the initializer of the enumeration, however, we set the instance to Unknown. The result is that the connectionState variable is equal to ConnectionState.Unknown.

Value Types

Like structures, enumerations are value types, which means that an enumeration is not passed by reference, like class instances, but by value. The following example illustrates this.

Even though we assign connectionState1 to connectionState2, the values of connectionState1 and connectionState2 are different at the end of the example.

When connectionState1 is assigned to connectionState2, Swift creates a copy of connectionState1 and assigns that to connectionState2. In other words, connectionState1 and connectionState2 refer to two different ConnectionState instances.

Conclusion

Enums in Swift are incredibly powerful compared to, for example, enums in C. One of the most powerful aspects of enumerations is that they are a first class types in Swift. Type safety is a key aspect of the Swift language and enumerations fit perfectly in that mindset.

2017-05-17T14:57:00.139Z2017-05-17T14:57:00.139ZBart Jacobs

Quick Tip: Enumerations in Swift

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

Enumerations are a common design pattern in many programming languages. While you may be familiar with enumerations in C and Objective-C, Swift's implementation of enumerations is significantly more powerful and flexible. In this quick tip, you'll learn what's special about enumerations in Swift, how to use them in your projects, and what makes them so powerful.

1. What Is an Enumeration?

Enumerations aren't new and they're certainly not unique to Swift. However, if you're familiar with enumerations in C, then you're going to love Swift's powerful take on enumerations.

If enums or enumerations are new to you, then you may not be familiar with what they have to offer. In Swift, enumerations are first class types that define a list of possible values for that type.

An example might be the possible states of a network connection. The possible states could be:

  • disconnected
  • connecting
  • connected

We could add a fourth state for the case the state is unknown. With this example in mind, let's see how to define and implement such an enumeration.

Basics

Like I said, enumerations are first class types in Swift. An enumeration definition looks very similar to a class or structure definition. In the example below, we define the ConnectionState enumeration.

The name of the enumeration is preceded by the enum keyword and followed by a pair of curly braces. The ConnectionState enumeration will define the possible states of a network connection. To define these states, we add member values or members to the enumeration's definition. The definition of a member value always starts with the case keyword.

In C or Objective-C, the above enumeration would look a bit different as illustrated in the example below. Each value of the enumeration corresponds with an integer, for example, ConnectionStateUnknown equals 0, ConnectionStateDisconnected equals 1, etc.

This isn't true in Swift. The members of an enumeration don't automatically correspond with an integer value. The members of the ConnectionState enumeration are values themselves and they are of type ConnectionState. This makes working with enumerations safer and more explicit.

Raw Values

It is possible to explicitly specify the values of the members of an enumeration. In the following example, the members of the ConnectionState enumeration have a raw value of type Int. Each member is assigned a raw value, corresponding with an integer.

Note that we specify the type of the raw values in the enumeration's definition and that no two member values can have the same raw value. If we only specify a value for the Unknown member, then Swift will automatically increment the value of the Unknown member and assign unique values to the other members of the enumeration. To better illustrate this, the below example is identical to the previous definition of the ConnectionState enumeration.

2. Working with Enumerations

Initialization

Using the ConnectionState enumeration is similar to using any other type in Swift. In the next example, we declare a variable, connectionState, and set its value to ConnectionState.Connecting.

The value of connectionState is ConnectionState.Connecting and the variable is of type ConnectionState.

Swift's type inference is very convenient when working with enumerations. Because we declared connectionState as being of type ConnectionState, we can now assign a new value by using the shorthand dot syntax for enumerations.

Control Flow

Using enumerations in an if or switch statement is straightforward. Remember that switch statements need to be exhaustive. Add a default case if necessary.

The following example demonstrates how the ConnectionState enum can be used. It also shows how to access the associated value of an enum member. The canConnect function accepts a ConnectionState instance and returns a Bool.

The canConnect function only returns true if the ConnectionState instance passed to the function is equal to .Connected and its associated value is an Int equal to 3000. Note that the associated value of the Connected member is available in the switch statement as a constant named port, which we can then use in the corresponding case.

3. Associated Values

Another compelling feature of Swift enums are associated values. Each member of an enum can have an associated value. Associated values are very flexible. For example, associated values of different members of the same enum don't need to be of the same type. Take a look at the following example to better understand the concept of associated values.

The Unknown and Disconnected members don't have an associated value. TheConnecting member has an associated value of type (Int, Double), specifying the port number and timeout interval of the connection. The Connected member has an associated value of type Int, specifying the port number.

It's important to understand that an associated value is linked to or associated with a member of the enumeration. The member's value remains unchanged. The next example illustrates how to create a ConnectionState instance with an associated value.

4. Methods and Value Types

Methods

Enumerations are pretty powerful in Swift. Enumerations can even define methods, such as an initializer to select a default member value if none was specified.

In this example, we initialize an instance of the ConnectionState enumeration without explicitly specifying a value for it. In the initializer of the enumeration, however, we set the instance to Unknown. The result is that the connectionState variable is equal to ConnectionState.Unknown.

Value Types

Like structures, enumerations are value types, which means that an enumeration is not passed by reference, like class instances, but by value. The following example illustrates this.

Even though we assign connectionState1 to connectionState2, the values of connectionState1 and connectionState2 are different at the end of the example.

When connectionState1 is assigned to connectionState2, Swift creates a copy of connectionState1 and assigns that to connectionState2. In other words, connectionState1 and connectionState2 refer to two different ConnectionState instances.

Conclusion

Enums in Swift are incredibly powerful compared to, for example, enums in C. One of the most powerful aspects of enumerations is that they are a first class types in Swift. Type safety is a key aspect of the Swift language and enumerations fit perfectly in that mindset.

2017-05-17T14:57:00.139Z2017-05-17T14:57:00.139ZBart Jacobs

Swift Animation Basics

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

In my recent course Go Further With Swift, I showed you how to code a functional iOS weather app with live weather data, custom UI components, and some slick animations to bring everything to life.

In this video tutorial from the course, you'll see how to start adding some animation to an iOS app with Swift. We'll begin with constraint-based animation and then advance to cross-fading the background image with a handy technique.

Adding animation in Swift

Watch the Full Course

In the full course, Go Further With Swift: Animation, Networking, and Custom Controls, you'll learn some advanced skills for building professional-quality iOS apps. 

App store customers expect animated, engaging apps with clear feedback on UI events. They want apps that connect to the web to get relevant, up-to-date information. And they want apps that stand out with unique custom interfaces. You'll learn how to add all those features in this course.

Of, if you want to learn the basics of iOS app development with Swift, try some of these courses instead:

And don't forget that you can find some fantastic, full-featured iOS app templates on Envato Market to get your app development off to a flying start.

2017-05-18T16:37:56.000Z2017-05-18T16:37:56.000ZMarkus Mühlberger

How to Use Android O's Autofill Framework

$
0
0

Auto form fill, often shortened to just autofill, is a feature browsers have supported for years now. Most of us use it all the time. I, for one, find it indispensable during tasks such as filling out a registration form or completing a checkout process.

The latest release of Android, Android O, brings similar functionality to Android apps. In other words, Android can now help users fill out forms that belong to all the apps they have installed on their devices. This was a much-awaited feature because typing with a virtual keyboard on a small screen tends to be quite a hassle.

As an app developer, you can use the new Autofill Framework to create your own custom autofill service, a service that decides how to populate an app's input fields. In this tutorial, I'll show you how.

Prerequisites

To be able to follow this tutorial, you'll need:

1. Create a New Project

Fire up Android Studio and create a new project with an empty activity. You must, of course, remember to choose Android 7+ in the Target Android Devices dialog.

Target android devices dialog

This project will need a few widgets that belong to the Design Support Library, so open the app module's build.gradle file and add the following compile dependency to it:

Lastly, press the Sync Now button to update the project.

2. Create a Settings Activity

In this tutorial, we'll be creating an app containing a very simple autofill service that targets only those input fields where the user is expected to type in an email address. Because almost every other app on Google Play today asks for an email address, this service will be quite useful.

Our service obviously needs to know what the user's email addresses are. Therefore, let us now build an activity where the user can type in and save two email addresses.

Step 1: Define the Layout

As you might expect, the layout of the activity will contain two EditText widgets where the user can type in his or her email addresses. If you want it to adhere to the guidelines of Material Design, placing the EditText widgets inside TextInputLayout containers is a good idea.

Additionally, the layout must have a Button widget the user can press to save the email addresses.

You are free to place the widgets anywhere you want. Nevertheless, for now, I suggest you place them all inside a LinearLayout whose orientation is vertical.

In the above code, you can see that the Button widget has an onClick attribute pointing to a method. Click on the yellow light bulb beside this attribute in Android Studio to generate a stub for it in the associated Activity class.

Step 2: Save the Email Addresses

We'll be using a shared preferences file called EMAIL_STORAGE to save our data. You can use the getSharedPreferences() method of your Activity class to access the file. Additionally, to be able to write to the file, you must call its edit() method, which generates a SharedPreferences.Editor object.

Accordingly, add the following code inside the saveEmailAddresses() method:

To fetch the email addresses the user has typed into the EditText widgets, you'll have to first get references to them using the findViewById() method, and then call their getText() methods.

At this point, you can call the putString() method of the editor to add the email addresses to the preferences file as two key value pairs. After you do so, don't forget to call the commit() method to make your changes permanent.

Step 3: Create a Meta-Data File

The settings activity we created in the previous step is currently just an ordinary activity. To let the Android platform know that it is a settings activity for an autofill service, we must create a meta-data XML file saying so.

Create a new XML file called email_address_filler.xml in the project's res/xml folder. Inside it, add an <autofill-service> tag and set the value of its settingsActivity attribute to the name of your Activity class.

You can now run the app, type in two email addresses, and press the Save button to save them.

Settings activity running

3. Create an Autofill Service

Any class that extends the abstract AutoFillService class can serve as an autofill service. So start by creating a new Java class with File > New > Java Class. In the dialog that pops up, name the class EmailAddressFiller and make sure that you set the value of the Superclass field to AutoFillService.

Create new class dialog

Android Studio will now prompt you to generate stubs for two abstract methods: onSaveRequest() and onFillRequest(). In this tutorial, we'll be focusing only the onFillRequest() method, which is automatically called whenever the user opens an activity—of any app—containing input fields.

Step 1: Analyze View Hierarchies

An autofill service needs to analyze an app's user interface and identify input fields it can fill. That's why the onFillRequest() method receives an AssistStructure object, which contains details about all the widgets that are currently visible on the screen. More precisely, it contains a tree of ViewNode objects. 

If you've never seen such a tree, I suggest you use the uiautomatorviewer tool, which is part of the Android SDK, to analyze the layout hierarchies of a few apps. For example, here's what the layout hierarchy of Android's default mail app looks like:

View hierarchy of default mail app

Naturally, to analyze all nodes of a tree, you need a recursive method. Let's create one now:

As you can see, this method has a ViewNode and a List as its parameters. We'll be using the List to store all the input fields that expect email addresses.

You might now be wondering how you can programmatically tell if an input field expects an email address. Well, there's really no foolproof approach you can follow. For now, we're going to assume that all app developers always give meaningful resource IDs to their input fields. Based on that assumption, we can simply pick all input fields whose resource IDs contain strings such as "email" and "username".

Accordingly, add the following code to the method:

Next, whenever we encounter a ViewNode object that contains more ViewNode objects, we must recursively call the identifyEmailFields() method to analyze all its children. The following code shows you how:

At this point, we can call the identifyEmailFields() method inside the onFillRequest() method and pass the root node of the view hierarchy to it.

If our service is unable to identify any input fields for emails, it should do nothing. Therefore, add the following code to it:

Step 2: Create and Populate Remote Views

If our service does identify an input field it can fill, it must populate a drop-down list that will be shown below the input field. Doing so, however, is not straightforward because neither the input field nor the drop-down list belongs to our app.

To populate the drop-down list, we must use RemoteViews objects. As its name suggests, a RemoteViews object is a collection of views that can be displayed in another app.

To initialize a RemoteViews object, you'll need a layout XML file. Let's create one now called email_suggestion.xml. For now, it can contain just one TextView widget to display an email address.

Accordingly, add the following code to email_suggestion.xml:

You can now go back to the onFillRequest() method and create two RemoteViews objects: one for the primary email, and another for the secondary.

The TextView widgets inside the RemoteViews objects must display the two email addresses we stored in a shared preferences file earlier. To open the file, use the getSharedPreferences() method again. Once it's opened, you can use its getString() method to fetch both the email addresses.

Finally, to set the contents of the remote TextView widgets, you must use the setTextViewText() method.

Step 3: Create Data Sets

We can now use the remote views to create autofill data sets that can be sent to any app. To keep this tutorial from getting too long, we'll be creating data sets only for the first email input field we encounter. The following code shows how to pick only the first email input field:

An autofill data set is nothing but an instance of the Dataset class, and can be built using the Dataset.Builder class.

When the user selects one of the email addresses our service shows in the drop-down list, it must set the contents of the associated input field using the setValue() method of the Dataset.Builder class. However, you cannot pass a ViewNode object to the setValue() method. It actually expects an autofill identifier, which must be obtained by calling the getAutoFillId() method of the ViewNode object.

Additionally, to specify the text that must be written into the input field, you must use the AutoFillValue.forText() method. The following code shows you how:

Before you send the data sets to an app, you must add them to a FillResponse object, which can be built using the FillResponse.Builder class. Call its addDataset() method twice to add both the data sets.

Once the FillResponse object is ready, pass it as an argument to the onSuccess() method of the FillCallback object, which is one of the parameters of the onFillRequest() method.

Step 4: Update the Manifest

Like all services, the autofill service too must be declared in the project's AndroidManifest.xml file. While doing so, you must make sure that it is protected by the android.permission.BIND_AUTO_FILL permission.

This service also needs an <intent-filter> tag that allows it to respond to the android.service.autofill.AutoFillService action, and a <meta-data> tag that points to the meta-data XML file we created in an earlier step.

Accordingly, add the following lines to your manifest file:

Our autofill service and app are now ready. Build the project and install the app on your device.

4. Activate and Use the Autofill Service

To activate the autofill service, open your device's Settings app and navigate to Apps & Notifications > Advanced > Default apps > Autofill app. In the next screen, select your app from the list of available autofill apps.

Autofill app selection screen

You can now open any app that asks for an email address to see your autofill service in action. For example, here's what you'd see on the login screens of Instagram and Pinterest:

Autofill suggestions displayed for two popular apps

Conclusion

You now know how to create and use a custom autofill service for Android. Feel free to extend it to support other common fields, such as first name or phone number. You can also try identifying input fields using other attributes, such as labels and hints.

To learn more about the Autofill Framework, do refer to its official documentation. And in the meantime, check out some of our other posts about Android O and Android app development!

2017-05-18T17:00:00.000Z2017-05-18T17:00:00.000ZAshraff Hathibelagal

How to Use Android O's Autofill Framework

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

Auto form fill, often shortened to just autofill, is a feature browsers have supported for years now. Most of us use it all the time. I, for one, find it indispensable during tasks such as filling out a registration form or completing a checkout process.

The latest release of Android, Android O, brings similar functionality to Android apps. In other words, Android can now help users fill out forms that belong to all the apps they have installed on their devices. This was a much-awaited feature because typing with a virtual keyboard on a small screen tends to be quite a hassle.

As an app developer, you can use the new Autofill Framework to create your own custom autofill service, a service that decides how to populate an app's input fields. In this tutorial, I'll show you how.

Prerequisites

To be able to follow this tutorial, you'll need:

1. Create a New Project

Fire up Android Studio and create a new project with an empty activity. You must, of course, remember to choose Android 7+ in the Target Android Devices dialog.

Target android devices dialog

This project will need a few widgets that belong to the Design Support Library, so open the app module's build.gradle file and add the following compile dependency to it:

Lastly, press the Sync Now button to update the project.

2. Create a Settings Activity

In this tutorial, we'll be creating an app containing a very simple autofill service that targets only those input fields where the user is expected to type in an email address. Because almost every other app on Google Play today asks for an email address, this service will be quite useful.

Our service obviously needs to know what the user's email addresses are. Therefore, let us now build an activity where the user can type in and save two email addresses.

Step 1: Define the Layout

As you might expect, the layout of the activity will contain two EditText widgets where the user can type in his or her email addresses. If you want it to adhere to the guidelines of Material Design, placing the EditText widgets inside TextInputLayout containers is a good idea.

Additionally, the layout must have a Button widget the user can press to save the email addresses.

You are free to place the widgets anywhere you want. Nevertheless, for now, I suggest you place them all inside a LinearLayout whose orientation is vertical.

In the above code, you can see that the Button widget has an onClick attribute pointing to a method. Click on the yellow light bulb beside this attribute in Android Studio to generate a stub for it in the associated Activity class.

Step 2: Save the Email Addresses

We'll be using a shared preferences file called EMAIL_STORAGE to save our data. You can use the getSharedPreferences() method of your Activity class to access the file. Additionally, to be able to write to the file, you must call its edit() method, which generates a SharedPreferences.Editor object.

Accordingly, add the following code inside the saveEmailAddresses() method:

To fetch the email addresses the user has typed into the EditText widgets, you'll have to first get references to them using the findViewById() method, and then call their getText() methods.

At this point, you can call the putString() method of the editor to add the email addresses to the preferences file as two key value pairs. After you do so, don't forget to call the commit() method to make your changes permanent.

Step 3: Create a Meta-Data File

The settings activity we created in the previous step is currently just an ordinary activity. To let the Android platform know that it is a settings activity for an autofill service, we must create a meta-data XML file saying so.

Create a new XML file called email_address_filler.xml in the project's res/xml folder. Inside it, add an <autofill-service> tag and set the value of its settingsActivity attribute to the name of your Activity class.

You can now run the app, type in two email addresses, and press the Save button to save them.

Settings activity running

3. Create an Autofill Service

Any class that extends the abstract AutoFillService class can serve as an autofill service. So start by creating a new Java class with File > New > Java Class. In the dialog that pops up, name the class EmailAddressFiller and make sure that you set the value of the Superclass field to AutoFillService.

Create new class dialog

Android Studio will now prompt you to generate stubs for two abstract methods: onSaveRequest() and onFillRequest(). In this tutorial, we'll be focusing only the onFillRequest() method, which is automatically called whenever the user opens an activity—of any app—containing input fields.

Step 1: Analyze View Hierarchies

An autofill service needs to analyze an app's user interface and identify input fields it can fill. That's why the onFillRequest() method receives an AssistStructure object, which contains details about all the widgets that are currently visible on the screen. More precisely, it contains a tree of ViewNode objects. 

If you've never seen such a tree, I suggest you use the uiautomatorviewer tool, which is part of the Android SDK, to analyze the layout hierarchies of a few apps. For example, here's what the layout hierarchy of Android's default mail app looks like:

View hierarchy of default mail app

Naturally, to analyze all nodes of a tree, you need a recursive method. Let's create one now:

As you can see, this method has a ViewNode and a List as its parameters. We'll be using the List to store all the input fields that expect email addresses.

You might now be wondering how you can programmatically tell if an input field expects an email address. Well, there's really no foolproof approach you can follow. For now, we're going to assume that all app developers always give meaningful resource IDs to their input fields. Based on that assumption, we can simply pick all input fields whose resource IDs contain strings such as "email" and "username".

Accordingly, add the following code to the method:

Next, whenever we encounter a ViewNode object that contains more ViewNode objects, we must recursively call the identifyEmailFields() method to analyze all its children. The following code shows you how:

At this point, we can call the identifyEmailFields() method inside the onFillRequest() method and pass the root node of the view hierarchy to it.

If our service is unable to identify any input fields for emails, it should do nothing. Therefore, add the following code to it:

Step 2: Create and Populate Remote Views

If our service does identify an input field it can fill, it must populate a drop-down list that will be shown below the input field. Doing so, however, is not straightforward because neither the input field nor the drop-down list belongs to our app.

To populate the drop-down list, we must use RemoteViews objects. As its name suggests, a RemoteViews object is a collection of views that can be displayed in another app.

To initialize a RemoteViews object, you'll need a layout XML file. Let's create one now called email_suggestion.xml. For now, it can contain just one TextView widget to display an email address.

Accordingly, add the following code to email_suggestion.xml:

You can now go back to the onFillRequest() method and create two RemoteViews objects: one for the primary email, and another for the secondary.

The TextView widgets inside the RemoteViews objects must display the two email addresses we stored in a shared preferences file earlier. To open the file, use the getSharedPreferences() method again. Once it's opened, you can use its getString() method to fetch both the email addresses.

Finally, to set the contents of the remote TextView widgets, you must use the setTextViewText() method.

Step 3: Create Data Sets

We can now use the remote views to create autofill data sets that can be sent to any app. To keep this tutorial from getting too long, we'll be creating data sets only for the first email input field we encounter. The following code shows how to pick only the first email input field:

An autofill data set is nothing but an instance of the Dataset class, and can be built using the Dataset.Builder class.

When the user selects one of the email addresses our service shows in the drop-down list, it must set the contents of the associated input field using the setValue() method of the Dataset.Builder class. However, you cannot pass a ViewNode object to the setValue() method. It actually expects an autofill identifier, which must be obtained by calling the getAutoFillId() method of the ViewNode object.

Additionally, to specify the text that must be written into the input field, you must use the AutoFillValue.forText() method. The following code shows you how:

Before you send the data sets to an app, you must add them to a FillResponse object, which can be built using the FillResponse.Builder class. Call its addDataset() method twice to add both the data sets.

Once the FillResponse object is ready, pass it as an argument to the onSuccess() method of the FillCallback object, which is one of the parameters of the onFillRequest() method.

Step 4: Update the Manifest

Like all services, the autofill service too must be declared in the project's AndroidManifest.xml file. While doing so, you must make sure that it is protected by the android.permission.BIND_AUTO_FILL permission.

This service also needs an <intent-filter> tag that allows it to respond to the android.service.autofill.AutoFillService action, and a <meta-data> tag that points to the meta-data XML file we created in an earlier step.

Accordingly, add the following lines to your manifest file:

Our autofill service and app are now ready. Build the project and install the app on your device.

4. Activate and Use the Autofill Service

To activate the autofill service, open your device's Settings app and navigate to Apps & Notifications > Advanced > Default apps > Autofill app. In the next screen, select your app from the list of available autofill apps.

Autofill app selection screen

You can now open any app that asks for an email address to see your autofill service in action. For example, here's what you'd see on the login screens of Instagram and Pinterest:

Autofill suggestions displayed for two popular apps

Conclusion

You now know how to create and use a custom autofill service for Android. Feel free to extend it to support other common fields, such as first name or phone number. You can also try identifying input fields using other attributes, such as labels and hints.

To learn more about the Autofill Framework, do refer to its official documentation. And in the meantime, check out some of our other posts about Android O and Android app development!

2017-05-18T17:00:00.000Z2017-05-18T17:00:00.000ZAshraff Hathibelagal

Securing iOS Data at Rest: Protecting the User's Data

$
0
0

This is the first of three articles on securing user data at rest. In this post, we'll start off with the basics of protecting data on iOS so you can learn the current best practices for storing data securely with Swift.

Any app that saves the user's data has to take care of the security and privacy of that data. As we've seen with recent data breaches, there can be very serious consequences for failing to protect your users' stored data. In this tutorial, you'll learn some best practices for protecting your users' data.

Permissions

Before we get into storing your custom data, let's take a look at data that can be shared by system apps. 

For many iOS versions, it has been required to request app permissions to use and store some of the user's private data that is external to the app, such as when saving and loading pictures to the photo library. Starting in iOS 10, any APIs that access the user's private data require you to declare that access ahead of time in your project's info.plist file. 

There are many frameworks that can access data outside of your app, and each framework has a corresponding privacy key.

  • Bluetooth Sharing: NSBluetoothPeripheralUsageDescription
  • Calendar: NSCalendarsUsageDescription
  • CallKit: NSVoIPUsageDescription
  • Camera: NSCameraUsageDescription
  • Contacts: NSContactsUsageDescription
  • Health: NSHealthShareUsageDescription, NSHealthUpdateUsageDescription
  • HomeKit: NSHomeKitUsageDescription
  • Location: NSLocationAlwaysUsageDescription, NSLocationUsageDescription, NSLocationWhenInUseUsageDescription
  • Media Library: NSAppleMusicUsageDescription
  • Microphone: NSMicrophoneUsageDescription
  • Motion: NSMotionUsageDescription
  • Photos: NSPhotoLibraryUsageDescription
  • Reminders: NSRemindersUsageDescription
  • Speech Recognition: NSSpeechRecognitionUsageDescription
  • SiriKit: NSSiriUsageDescription
  • TV Provider: NSVideoSubscriberAccountUsageDescription

For example, here is an entry in info.plist to allow your app to load and store values to the calendar.

If a usage description is missing when the API tries to access the data, the app will simply crash.

The Data Protection API

For any user data that's internal to the app, the first thing to think about is whether you need to store the information, and what data is essential to the app. Keep as much of that essential data in working memory instead of in file storage. This is especially important for any personally identifiable information. 

But, if you must store data, it's a good idea to enable Apple's Data Protection.

Data Protection encrypts the contents of your app’s container. It relies on the user having a passcode, and thus the security of the encryption is tied to the strength of the passcode. With Touch ID and the upgraded file system encryption introduced in iOS 10.3, the data protection system has had many improvements. You can enable data protection across your app by turning on Data Protection in the Capabilities section of your project file. This updates your provisioning profile and entitlements file to include the Data Protection capability. Data Protection offers four levels of protection, depicted by the FileProtectionType structure:

  • none: no protection.
  • complete: data is not accessible while the device is locked. This is the recommended setting for most applications.
  • completeUnlessOpen: data is accessible when the device is unlocked, and continues to be accessible until the file is closed, even if the user locks the device. Files can also be created when the device is locked. This option is good for when you need to open a file to process and have the process continue even if the user puts the app into the background and locks the device. An example might be a job that uploads a file to a server.
  • completeUntilFirstUserAuthentication: when the device is booted, files are not accessible until the user first unlocks the device. After that, files are available even when the device is locked again. The option is good for files that need to be accessed sometime later in the background when the device is locked, such as during a background fetch job.

complete is the default level. To help avoid crashes when your code tries to access data that is locked, you can register for notifications via UIApplicationProtectedDataDidBecomeAvailable and UIApplicationProtectedDataWillBecomeUnavailable to find out when the data is available.

Additionally, you can also check the UIApplication.shared.isProtectedDataAvailable flag.

One important thing to keep in mind when enabling data protection is that if you are using any background services such as background fetch, that code may need access to your data in the background when the device is locked. For those files, you will need to set a protection level of completeUntilFirstUserAuthentication. You can control the protection level of each file individually when creating files and directories using the FileManager class.

You can also set the protection level when you write to a file. The Data object has a method that can write its data to a file, and you can set the protection level when you call this method.

You can also set the protection level when setting up your Core Data model.

To change the protection level of an existing file, use the following:

Data Integrity

Part of protecting your stored data includes checking its integrity. It's good practice not to blindly trust the data you are loading from storage; it may have been accidentally or maliciously altered. The NSSecureCoding protocol can be used to safely load and save your data objects from storage. It will make sure the objects you load contain the expected data. If you will be saving your own object, you can conform to the secure coding protocol inside your class.

The class must be inherited from NSObject. Then, to turn on secure coding, override the supportsSecureCoding protocol method.

If your custom object is deserialized with init?(coder aDecoder: NSCoder), the decodeObject(forKey:) method should be replaced with decodeObject(of:forKey:), which makes sure that the correct object types are unpacked from storage.

If you are using NSKeyedUnarchiver to load data from storage, make sure to set its requiresSecureCoding property.

Turning on secure coding for your save operations will prevent you from accidentally archiving an object that does not adhere to the secure coding protocol.

Beyond NSSecureCoding, it’s always good to implement your own data validation checks upon unpacking any archive or receiving any arbitrary input in general.

Data Trails

As iOS continues to evolve, there are always new features that have the potential to leak stored data. Starting in iOS 9, you can have your content indexed in the Spotlight search, and on iOS 10 you can expose your content to Widgets such as the Today Widget that shows up on the lock screen. Use caution if you would like to expose your content with these new features. You might end up sharing more than you planned to!

iOS 10 also adds a new Handoff feature where your copied pasteboard data is automatically shared between devices. Again, be careful not to expose any sensitive data in the pasteboard to Handoff. You can do this by marking the sensitive content as localOnly. You can also set an expiry date and time for the data.

Files that are saved to the device's storage can automatically get backed up, either in iTunes or in iCloud. Even though backups can be encrypted, it's a good idea to exclude any sensitive files that don't even need to leave the device. This can be done by setting the isExcludedFromBackup flag on the file.

The animation that happens when putting an app into the background is achieved by iOS taking a screenshot of your app which it then uses for the animation. When you look at the list of open apps on the app switcher, this screenshot is used there too. The screenshot gets stored on the device. 

It's a good idea to hide any views revealing sensitive data so that the data isn't captured in the screenshot. To do this, set up a notification when the application is going to the background and set the hidden property for the UI elements you want to exclude. They will be hidden before iOS captures the screen. Then when coming to the foreground, you can unhide the UI elements.

Remove your notifications when the view disappears.

Your app also has a keyboard cache for text fields that have auto-correct enabled. Text that the user types, along with newly learned words, are stored in the cache so that it is possible to retrieve various words that the user has previously entered in your application. The only way to disable the keyboard cache is to turn off the auto-correct option.

You should mark password fields as secure text entry. Secure text fields don't display the password or use the keyboard cache.

Debug logs are saved to a file and could be retrieved for production builds of your app. Even when you're coding and debugging your app, make sure not to log sensitive information such as passwords and keys to the console. You might forget to remove that information from the logs before submitting your code to the app store! While debugging, it's safer instead to use a breakpoint to view sensitive variables.

Network connections may also get cached to storage. More information about removing and disabling the network cache can be found in the article Securing Communications on iOS.

Destroying Data

You may already know that when a file on a computer is deleted, often the file itself is not removed; only the reference for the file is removed. To actually remove the file, you can overwrite the file with random data before removing it. 

The switch to solid state drives has made it hard to guarantee the data has been destroyed, and the best way to securely delete data is open to debate. However, this tutorial would not be complete without an example of how to wipe data from storage. Because of some other debates about the Swift optimizer, and because we hope to guarantee that each byte of the file is actually being overwritten, we are implementing this function in C. 

The implementation below can go inside a .c file. You will need to add the function definition or the file that contains the function into your bridging header in order to use the function from Swift. You may then want to call this function right before places where you use FileManager's removeFile methods. Perhaps you may want to implement the best practices described in this and the upcoming tutorials on an app update. You could then wipe the previous unprotected data during migration.

Conclusion

In this article, you have learned about setting permissions for the data that your app has access to, as well as how to ensure basic file protection and integrity. We also looked at some ways that user data could be leaked accidentally from your app. Your users put their trust in you to protect their data. Following these best practices will help you repay that confidence.

While you're here, check out some of our other posts on iOS app development!


2017-05-19T09:00:00.000Z2017-05-19T09:00:00.000ZCollin Stuart

Securing iOS Data at Rest: Protecting the User's Data

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

This is the first of three articles on securing user data at rest. In this post, we'll start off with the basics of protecting data on iOS so you can learn the current best practices for storing data securely with Swift.

Any app that saves the user's data has to take care of the security and privacy of that data. As we've seen with recent data breaches, there can be very serious consequences for failing to protect your users' stored data. In this tutorial, you'll learn some best practices for protecting your users' data.

Permissions

Before we get into storing your custom data, let's take a look at data that can be shared by system apps. 

For many iOS versions, it has been required to request app permissions to use and store some of the user's private data that is external to the app, such as when saving and loading pictures to the photo library. Starting in iOS 10, any APIs that access the user's private data require you to declare that access ahead of time in your project's info.plist file. 

There are many frameworks that can access data outside of your app, and each framework has a corresponding privacy key.

  • Bluetooth Sharing: NSBluetoothPeripheralUsageDescription
  • Calendar: NSCalendarsUsageDescription
  • CallKit: NSVoIPUsageDescription
  • Camera: NSCameraUsageDescription
  • Contacts: NSContactsUsageDescription
  • Health: NSHealthShareUsageDescription, NSHealthUpdateUsageDescription
  • HomeKit: NSHomeKitUsageDescription
  • Location: NSLocationAlwaysUsageDescription, NSLocationUsageDescription, NSLocationWhenInUseUsageDescription
  • Media Library: NSAppleMusicUsageDescription
  • Microphone: NSMicrophoneUsageDescription
  • Motion: NSMotionUsageDescription
  • Photos: NSPhotoLibraryUsageDescription
  • Reminders: NSRemindersUsageDescription
  • Speech Recognition: NSSpeechRecognitionUsageDescription
  • SiriKit: NSSiriUsageDescription
  • TV Provider: NSVideoSubscriberAccountUsageDescription

For example, here is an entry in info.plist to allow your app to load and store values to the calendar.

If a usage description is missing when the API tries to access the data, the app will simply crash.

The Data Protection API

For any user data that's internal to the app, the first thing to think about is whether you need to store the information, and what data is essential to the app. Keep as much of that essential data in working memory instead of in file storage. This is especially important for any personally identifiable information. 

But, if you must store data, it's a good idea to enable Apple's Data Protection.

Data Protection encrypts the contents of your app’s container. It relies on the user having a passcode, and thus the security of the encryption is tied to the strength of the passcode. With Touch ID and the upgraded file system encryption introduced in iOS 10.3, the data protection system has had many improvements. You can enable data protection across your app by turning on Data Protection in the Capabilities section of your project file. This updates your provisioning profile and entitlements file to include the Data Protection capability. Data Protection offers four levels of protection, depicted by the FileProtectionType structure:

  • none: no protection.
  • complete: data is not accessible while the device is locked. This is the recommended setting for most applications.
  • completeUnlessOpen: data is accessible when the device is unlocked, and continues to be accessible until the file is closed, even if the user locks the device. Files can also be created when the device is locked. This option is good for when you need to open a file to process and have the process continue even if the user puts the app into the background and locks the device. An example might be a job that uploads a file to a server.
  • completeUntilFirstUserAuthentication: when the device is booted, files are not accessible until the user first unlocks the device. After that, files are available even when the device is locked again. The option is good for files that need to be accessed sometime later in the background when the device is locked, such as during a background fetch job.

complete is the default level. To help avoid crashes when your code tries to access data that is locked, you can register for notifications via UIApplicationProtectedDataDidBecomeAvailable and UIApplicationProtectedDataWillBecomeUnavailable to find out when the data is available.

Additionally, you can also check the UIApplication.shared.isProtectedDataAvailable flag.

One important thing to keep in mind when enabling data protection is that if you are using any background services such as background fetch, that code may need access to your data in the background when the device is locked. For those files, you will need to set a protection level of completeUntilFirstUserAuthentication. You can control the protection level of each file individually when creating files and directories using the FileManager class.

You can also set the protection level when you write to a file. The Data object has a method that can write its data to a file, and you can set the protection level when you call this method.

You can also set the protection level when setting up your Core Data model.

To change the protection level of an existing file, use the following:

Data Integrity

Part of protecting your stored data includes checking its integrity. It's good practice not to blindly trust the data you are loading from storage; it may have been accidentally or maliciously altered. The NSSecureCoding protocol can be used to safely load and save your data objects from storage. It will make sure the objects you load contain the expected data. If you will be saving your own object, you can conform to the secure coding protocol inside your class.

The class must be inherited from NSObject. Then, to turn on secure coding, override the supportsSecureCoding protocol method.

If your custom object is deserialized with init?(coder aDecoder: NSCoder), the decodeObject(forKey:) method should be replaced with decodeObject(of:forKey:), which makes sure that the correct object types are unpacked from storage.

If you are using NSKeyedUnarchiver to load data from storage, make sure to set its requiresSecureCoding property.

Turning on secure coding for your save operations will prevent you from accidentally archiving an object that does not adhere to the secure coding protocol.

Beyond NSSecureCoding, it’s always good to implement your own data validation checks upon unpacking any archive or receiving any arbitrary input in general.

Data Trails

As iOS continues to evolve, there are always new features that have the potential to leak stored data. Starting in iOS 9, you can have your content indexed in the Spotlight search, and on iOS 10 you can expose your content to Widgets such as the Today Widget that shows up on the lock screen. Use caution if you would like to expose your content with these new features. You might end up sharing more than you planned to!

iOS 10 also adds a new Handoff feature where your copied pasteboard data is automatically shared between devices. Again, be careful not to expose any sensitive data in the pasteboard to Handoff. You can do this by marking the sensitive content as localOnly. You can also set an expiry date and time for the data.

Files that are saved to the device's storage can automatically get backed up, either in iTunes or in iCloud. Even though backups can be encrypted, it's a good idea to exclude any sensitive files that don't even need to leave the device. This can be done by setting the isExcludedFromBackup flag on the file.

The animation that happens when putting an app into the background is achieved by iOS taking a screenshot of your app which it then uses for the animation. When you look at the list of open apps on the app switcher, this screenshot is used there too. The screenshot gets stored on the device. 

It's a good idea to hide any views revealing sensitive data so that the data isn't captured in the screenshot. To do this, set up a notification when the application is going to the background and set the hidden property for the UI elements you want to exclude. They will be hidden before iOS captures the screen. Then when coming to the foreground, you can unhide the UI elements.

Remove your notifications when the view disappears.

Your app also has a keyboard cache for text fields that have auto-correct enabled. Text that the user types, along with newly learned words, are stored in the cache so that it is possible to retrieve various words that the user has previously entered in your application. The only way to disable the keyboard cache is to turn off the auto-correct option.

You should mark password fields as secure text entry. Secure text fields don't display the password or use the keyboard cache.

Debug logs are saved to a file and could be retrieved for production builds of your app. Even when you're coding and debugging your app, make sure not to log sensitive information such as passwords and keys to the console. You might forget to remove that information from the logs before submitting your code to the app store! While debugging, it's safer instead to use a breakpoint to view sensitive variables.

Network connections may also get cached to storage. More information about removing and disabling the network cache can be found in the article Securing Communications on iOS.

Destroying Data

You may already know that when a file on a computer is deleted, often the file itself is not removed; only the reference for the file is removed. To actually remove the file, you can overwrite the file with random data before removing it. 

The switch to solid state drives has made it hard to guarantee the data has been destroyed, and the best way to securely delete data is open to debate. However, this tutorial would not be complete without an example of how to wipe data from storage. Because of some other debates about the Swift optimizer, and because we hope to guarantee that each byte of the file is actually being overwritten, we are implementing this function in C. 

The implementation below can go inside a .c file. You will need to add the function definition or the file that contains the function into your bridging header in order to use the function from Swift. You may then want to call this function right before places where you use FileManager's removeFile methods. Perhaps you may want to implement the best practices described in this and the upcoming tutorials on an app update. You could then wipe the previous unprotected data during migration.

Conclusion

In this article, you have learned about setting permissions for the data that your app has access to, as well as how to ensure basic file protection and integrity. We also looked at some ways that user data could be leaked accidentally from your app. Your users put their trust in you to protect their data. Following these best practices will help you repay that confidence.

While you're here, check out some of our other posts on iOS app development!


2017-05-19T09:00:00.000Z2017-05-19T09:00:00.000ZCollin Stuart

Get Started With Ionic Services: Auth

$
0
0

One of Ionic's strengths is in the services that it offers on top of the framework. This includes services for authenticating users of your app, push notifications, and analytics. In this series, we'll be learning about those three services by creating an app which uses each of them.

The first service we're going to look at is the Auth service. This allows us to implement authentication in an Ionic app without writing a single line of back-end code. Or if you already have an existing authentication system, you can also use that. The service supports the following authentication methods:

  • Email/Password: user is registered by supplying their email and password.
  • Social Login: user is registered using their social media profile. This currently includes Facebook, Google, Twitter, Instagram, LinkedIn, and GitHub.
  • Custom: user is registered by making use of an existing authentication system. 

In this tutorial, we're only going to cover email/password and social login with Facebook. 

What You'll Be Creating

Before we proceed, it's always good to have a general idea of what we're going to create, and what the flow of the app will be like. The app will have the following pages:

  • home page
  • signup page
  • user page

Home Page

The home page is the default page of the app where the user can log in with their email/password or their Facebook account. 

home page

When the user clicks on the Login with Facebook button, a screen similar to the following is displayed, and once the user agrees, the user is logged in to the app:

Facebook login

Signup Page

The signup page is where the user can register by entering their email and password. Facebook login doesn't require any signup because the user info is supplied by the Facebook API. 

Signup page

User Page

The final page is the user page, which can be seen only when the user has already logged in. 

Bootstrap a New Ionic App

Now that you know what we're making, let's get started building our app!

First, we bootstrap a new Ionic app using the blank starter template:

Navigate inside the newly created authApp folder. This serves as the root directory of the project. 

To quickly get set up with the UI of the app, I've created a GitHub repo where you can find the starter source files. Download the repo, navigate inside the starter folder, and copy the src folder over to the root of the Ionic project that you just created. This contains the template files for each of the pages of the app. I'll explain to you in more detail what each of those files does in a later section.

Serve the project so you can immediately see your changes while developing the app:

Create an Ionic Account

Since we'll be using Ionic's back-end to handle user authentication, we need a way to manage the users of the app. This is where the Ionic account comes in. It allows you to manage your Ionic apps and the services that they use. This includes managing the Auth service. You can create an Ionic account by visiting the Ionic.io signup page.

Connect the App to Ionic Services

Next, navigate to the root directory of the project and install the Ionic Cloud plugin:

This plugin will allow the app to easily interact with Ionic services.

After that, you can initialize the app to use Ionic services:

This prompts you to log in with your Ionic account. Once you've entered the correct login details, the command-line tool will automatically create a new app record under your Ionic account. This record is connected to the app that you're developing. 

You can verify that this step has worked by opening the .io-config.json file and the ionic.config.json file at the root of your project. The app_id should be the same as the app ID assigned to the newly created app in your Ionic dashboard.

Home Page

Navigate inside the src/pages/home directory to see the files for the home page. Open the home.html file and you'll see the following:

This page will ask the user for their email and password or to log in with their Facebook account. If the user has no account yet, they can click on the signup button to access the signup page. We'll go back to the specifics of this page later on as we move on to the login part. I'm just showing it to you so you can see the code for navigating to the signup page.

Next, open the home.tsfile. For now, it only contains some boilerplate code for navigating to the signup and user page. Later on, we're going to go back to this page to add the code for logging the user in.

User Sign Up

The layout of the signup page is found in src/pages/signup-page/signup-page.html. Take a look at this file and you'll find a simple form with an email field and a password field.

Next, let's take a look at the signup-page.ts file.

Let's break this down. First, it imports the controllers for creating alerts and loaders:

Then, it imports the classes needed from the Cloud Client:

  • The Auth service which deals with user registration, login, and sign-out. 
  • UserDetails is the type used for defining the user details when registering or logging in a user. 
  • IDetailedError is used for determining the exact reason for the error that occurred. This allows us to provide user-friendly error messages to the user whenever an error occurs. 

Declare the variables to be used for storing the email and password input by the user. This should be the same as the name you've given to the value and ngModel attributes in the layout file. 

Next is the register method, which is called when the Register button is pressed. Let's code this method together. 

First it fires up a loader, and then makes it automatically close after five seconds (so that in case something goes wrong, the user isn't left with a loading animation that is spinning forever).

Next, let's create an object to store the user details:

Finally, we'll call the signup() method from the Auth service and supply the user details as the argument. This returns a promise, which we unwrap with then(). Once a success response is received from the back-end, the first function that you pass to then() will get executed; otherwise, the second function will get executed.

If an error response is received from Ionic Auth, we'll loop through the array of errors and construct an error message based on the type of error received. Here you can find the list of Auth signup errors that can occur.

Once that's done, you can try the app in your browser. The email/password login doesn't have any plugin or hardware dependencies, so you should be able to test it out in the browser. You can then find the newly registered user in the Auth tab of your Ionic app dashboard.

Setting Up Facebook App

The next step is to set up the app so that it can handle native Facebook logins. First, you need to create a Facebook app. You can do that by logging in to your Facebook account and then going to the Facebook Developer Site. From there, create a new app:

Create Facebook App

Once the app is created, click on the Add Product link on the sidebar and select Facebook Login. This will open the Quickstart screen by default. We don't really need that, so go ahead and click on the Settings link right below the Facebook Login. That should show you the following screen:

Facebook Settings

Here you need to enable the Embedded Browser OAuth Login setting and add https://api.ionic.io/auth/integrations/facebook as the value for the Valid OAuth redirect URIs. Save the changes once that's done.

Next, you need to connect Ionic Auth to the Facebook app that you've just created. Go to your Ionic dashboard and select the app that was created earlier (see the "Connect the App to Ionic Services" section). Click on the Settings tab and then User Auth. Under the Social Providers, click on the Setup button next to Facebook:

Ionic app settings social providers

Enter the App ID and App Secret of the Facebook app that you created earlier and hit Enable

Install the Facebook Plugin

Next, install the Facebook plugin for Cordova. Unlike most plugins, this requires you to supply a bit of information: the Facebook App ID and App Name. You can just copy this information from the Facebook app dashboard.

Configure Facebook Service

Once that's done, the last thing that you need to do is to go back to your project, open the src/app/app.module.ts file, and add the CloudSettings and CloudModule services from the cloud-angular package:

Declare the cloudSettings object. This contains the app_id of your Ionic app and any additional permissions (scope) that you want to ask from the users of your app. By default, this already asks for the email and public_profile

If you want to ask for more data from your users, you can find a list of permissions on this page: Facebook Login Permissions.

Next, let Ionic know of the cloudSettings you've just added:

Later on, when you add other social providers to your app, a similar process is followed.

Logging the User In

Now it's time to go back to the home page and make some changes. The HTML template already has everything we need, so we only need to update the script. Go ahead and open the src/pages/home/home.ts file. At the top of the file, import the following in addition to what you already have earlier:

Inside the constructor, determine if a user is currently logged in or not. If a user is already logged in, we automatically navigate to the User Page. 

Next, when the Login button is pressed, we start by displaying a loading animation.

As you saw in the src/pages/home/home.html file earlier, a string that represents which login button has been pressed (either the email/password login button or the Facebook login button) is passed to the login() function. This allows us to determine which login code to execute. If the type is 'fb', it means that the Facebook login button was pressed, so we call the login() method of the FacebookAuth service.

Otherwise, the email/password login button was pressed, and we should log the user in with the details entered in the login form.

Take a look at the final version of the home.ts file to see how it should all look.

User Page

The last page is the User page. 

The layout, in src/pages/user-page/user-page.html, displays the profile photo of the user and their username. If the user signed up with their email/password, the username will be the email address of the user and the profile photo will be the default profile photo assigned by Ionic. On the other hand, if the user signed up with Facebook, their profile photo will be their Facebook profile photo and their username will be their full name.

Next, look at the user-page.ts file. 

Under the ionic-angular package, we're importing the Platform service aside from NavController. This is used to get information about the current device. It also has methods for listening to hardware events such as when the hardware back button in Android is pressed.

And for the cloud-angular package, we need the Auth, FacebookAuth, and User services:

Inside the class constructor, determine if the user logged in with their email/password user or their Facebook account. Fill in the username and photo based on that. Then, below that, assign a function to be executed when the hardware back button is pressed. The registerBackButtonAction() accepts two arguments: the function to be executed and the priority. If there are more than one of these in the app, only the highest priority will be executed. But since we only need this in this screen, we just put in 1

The logoutUser() method contains the logic for logging the user out. The first thing it does is to determine if a user is actually logged in. If a user is logged in, we determine whether the user is a Facebook user or an email/password user. 

This can be done by checking the email property under the user.details object. If this property exists, that means that the user is an email/password user. So if it's otherwise, we assume that it's a Facebook user. Calling the logout() method in Auth and FacebookAuth clears out the current user of the app. 

Running the App on a Device

Now we can try out our app! First, set up the platform and build the debug apk:

For the Facebook login to work, you need to supply the hash of the apk file to the Facebook app. You can determine the hash by executing the following command:

Next, go to your Facebook app basic settings page and click on the Add Platform button in the bottom part of the screen. Select Android as the platform. You'll then see the following form:

Android platform settings

Fill out the Google Play Package Name and Key Hashes. You can put anything you want as the value for the Google Play Package Name as long as it follows the same format as the apps in Google Play (e.g. com.ionicframework.authapp316678). For the Key Hashes, you need to put in the hash returned from earlier. Don't forget to hit Save Changes when you're done.

Once that's done, you can now copy the android-debug.apk from the platforms/android/build/outputs/apk folder to your device, install it, and then run.

Conclusion and Next Steps

That's it! In this tutorial, you've learned how to make use of the Ionic Auth service to easily implement authentication in your Ionic app. We've used email/password authentication and Facebook login in this tutorial, but there are other options, and it should be easy for you to add those to your app as well. 

Here are some next steps you could try on your own that would take your app to the next level. 

  • Store additional user information—aside from the email and password, you can also store additional information for your users.
  • Use other social login providers—as mentioned at the beginning of the article, you can also implement social login with the following services: Google, Twitter, Instagram, LinkedIn, and GitHub.
  • Add a password reset functionalitypassword resets can be implemented using Ionic's password reset forms, or you can create your own.
  • Custom authentication—if you already have an existing back-end which handles the user authentication for your service, you might need to implement custom authentication.

That's all for now. Stay tuned for more articles on using Ionic services! And in the meantime, check out some of our other great posts on cross-platform mobile app development.

2017-05-22T15:00:00.000Z2017-05-22T15:00:00.000ZWernher-Bel Ancheta

Get Started With Ionic Services: Auth

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

One of Ionic's strengths is in the services that it offers on top of the framework. This includes services for authenticating users of your app, push notifications, and analytics. In this series, we'll be learning about those three services by creating an app which uses each of them.

The first service we're going to look at is the Auth service. This allows us to implement authentication in an Ionic app without writing a single line of back-end code. Or if you already have an existing authentication system, you can also use that. The service supports the following authentication methods:

  • Email/Password: user is registered by supplying their email and password.
  • Social Login: user is registered using their social media profile. This currently includes Facebook, Google, Twitter, Instagram, LinkedIn, and GitHub.
  • Custom: user is registered by making use of an existing authentication system. 

In this tutorial, we're only going to cover email/password and social login with Facebook. 

What You'll Be Creating

Before we proceed, it's always good to have a general idea of what we're going to create, and what the flow of the app will be like. The app will have the following pages:

  • home page
  • signup page
  • user page

Home Page

The home page is the default page of the app where the user can log in with their email/password or their Facebook account. 

home page

When the user clicks on the Login with Facebook button, a screen similar to the following is displayed, and once the user agrees, the user is logged in to the app:

Facebook login

Signup Page

The signup page is where the user can register by entering their email and password. Facebook login doesn't require any signup because the user info is supplied by the Facebook API. 

Signup page

User Page

The final page is the user page, which can be seen only when the user has already logged in. 

Bootstrap a New Ionic App

Now that you know what we're making, let's get started building our app!

First, we bootstrap a new Ionic app using the blank starter template:

Navigate inside the newly created authApp folder. This serves as the root directory of the project. 

To quickly get set up with the UI of the app, I've created a GitHub repo where you can find the starter source files. Download the repo, navigate inside the starter folder, and copy the src folder over to the root of the Ionic project that you just created. This contains the template files for each of the pages of the app. I'll explain to you in more detail what each of those files does in a later section.

Serve the project so you can immediately see your changes while developing the app:

Create an Ionic Account

Since we'll be using Ionic's back-end to handle user authentication, we need a way to manage the users of the app. This is where the Ionic account comes in. It allows you to manage your Ionic apps and the services that they use. This includes managing the Auth service. You can create an Ionic account by visiting the Ionic.io signup page.

Connect the App to Ionic Services

Next, navigate to the root directory of the project and install the Ionic Cloud plugin:

This plugin will allow the app to easily interact with Ionic services.

After that, you can initialize the app to use Ionic services:

This prompts you to log in with your Ionic account. Once you've entered the correct login details, the command-line tool will automatically create a new app record under your Ionic account. This record is connected to the app that you're developing. 

You can verify that this step has worked by opening the .io-config.json file and the ionic.config.json file at the root of your project. The app_id should be the same as the app ID assigned to the newly created app in your Ionic dashboard.

Home Page

Navigate inside the src/pages/home directory to see the files for the home page. Open the home.html file and you'll see the following:

This page will ask the user for their email and password or to log in with their Facebook account. If the user has no account yet, they can click on the signup button to access the signup page. We'll go back to the specifics of this page later on as we move on to the login part. I'm just showing it to you so you can see the code for navigating to the signup page.

Next, open the home.tsfile. For now, it only contains some boilerplate code for navigating to the signup and user page. Later on, we're going to go back to this page to add the code for logging the user in.

User Sign Up

The layout of the signup page is found in src/pages/signup-page/signup-page.html. Take a look at this file and you'll find a simple form with an email field and a password field.

Next, let's take a look at the signup-page.ts file.

Let's break this down. First, it imports the controllers for creating alerts and loaders:

Then, it imports the classes needed from the Cloud Client:

  • The Auth service which deals with user registration, login, and sign-out. 
  • UserDetails is the type used for defining the user details when registering or logging in a user. 
  • IDetailedError is used for determining the exact reason for the error that occurred. This allows us to provide user-friendly error messages to the user whenever an error occurs. 

Declare the variables to be used for storing the email and password input by the user. This should be the same as the name you've given to the value and ngModel attributes in the layout file. 

Next is the register method, which is called when the Register button is pressed. Let's code this method together. 

First it fires up a loader, and then makes it automatically close after five seconds (so that in case something goes wrong, the user isn't left with a loading animation that is spinning forever).

Next, let's create an object to store the user details:

Finally, we'll call the signup() method from the Auth service and supply the user details as the argument. This returns a promise, which we unwrap with then(). Once a success response is received from the back-end, the first function that you pass to then() will get executed; otherwise, the second function will get executed.

If an error response is received from Ionic Auth, we'll loop through the array of errors and construct an error message based on the type of error received. Here you can find the list of Auth signup errors that can occur.

Once that's done, you can try the app in your browser. The email/password login doesn't have any plugin or hardware dependencies, so you should be able to test it out in the browser. You can then find the newly registered user in the Auth tab of your Ionic app dashboard.

Setting Up Facebook App

The next step is to set up the app so that it can handle native Facebook logins. First, you need to create a Facebook app. You can do that by logging in to your Facebook account and then going to the Facebook Developer Site. From there, create a new app:

Create Facebook App

Once the app is created, click on the Add Product link on the sidebar and select Facebook Login. This will open the Quickstart screen by default. We don't really need that, so go ahead and click on the Settings link right below the Facebook Login. That should show you the following screen:

Facebook Settings

Here you need to enable the Embedded Browser OAuth Login setting and add https://api.ionic.io/auth/integrations/facebook as the value for the Valid OAuth redirect URIs. Save the changes once that's done.

Next, you need to connect Ionic Auth to the Facebook app that you've just created. Go to your Ionic dashboard and select the app that was created earlier (see the "Connect the App to Ionic Services" section). Click on the Settings tab and then User Auth. Under the Social Providers, click on the Setup button next to Facebook:

Ionic app settings social providers

Enter the App ID and App Secret of the Facebook app that you created earlier and hit Enable

Install the Facebook Plugin

Next, install the Facebook plugin for Cordova. Unlike most plugins, this requires you to supply a bit of information: the Facebook App ID and App Name. You can just copy this information from the Facebook app dashboard.

Configure Facebook Service

Once that's done, the last thing that you need to do is to go back to your project, open the src/app/app.module.ts file, and add the CloudSettings and CloudModule services from the cloud-angular package:

Declare the cloudSettings object. This contains the app_id of your Ionic app and any additional permissions (scope) that you want to ask from the users of your app. By default, this already asks for the email and public_profile

If you want to ask for more data from your users, you can find a list of permissions on this page: Facebook Login Permissions.

Next, let Ionic know of the cloudSettings you've just added:

Later on, when you add other social providers to your app, a similar process is followed.

Logging the User In

Now it's time to go back to the home page and make some changes. The HTML template already has everything we need, so we only need to update the script. Go ahead and open the src/pages/home/home.ts file. At the top of the file, import the following in addition to what you already have earlier:

Inside the constructor, determine if a user is currently logged in or not. If a user is already logged in, we automatically navigate to the User Page. 

Next, when the Login button is pressed, we start by displaying a loading animation.

As you saw in the src/pages/home/home.html file earlier, a string that represents which login button has been pressed (either the email/password login button or the Facebook login button) is passed to the login() function. This allows us to determine which login code to execute. If the type is 'fb', it means that the Facebook login button was pressed, so we call the login() method of the FacebookAuth service.

Otherwise, the email/password login button was pressed, and we should log the user in with the details entered in the login form.

Take a look at the final version of the home.ts file to see how it should all look.

User Page

The last page is the User page. 

The layout, in src/pages/user-page/user-page.html, displays the profile photo of the user and their username. If the user signed up with their email/password, the username will be the email address of the user and the profile photo will be the default profile photo assigned by Ionic. On the other hand, if the user signed up with Facebook, their profile photo will be their Facebook profile photo and their username will be their full name.

Next, look at the user-page.ts file. 

Under the ionic-angular package, we're importing the Platform service aside from NavController. This is used to get information about the current device. It also has methods for listening to hardware events such as when the hardware back button in Android is pressed.

And for the cloud-angular package, we need the Auth, FacebookAuth, and User services:

Inside the class constructor, determine if the user logged in with their email/password user or their Facebook account. Fill in the username and photo based on that. Then, below that, assign a function to be executed when the hardware back button is pressed. The registerBackButtonAction() accepts two arguments: the function to be executed and the priority. If there are more than one of these in the app, only the highest priority will be executed. But since we only need this in this screen, we just put in 1

The logoutUser() method contains the logic for logging the user out. The first thing it does is to determine if a user is actually logged in. If a user is logged in, we determine whether the user is a Facebook user or an email/password user. 

This can be done by checking the email property under the user.details object. If this property exists, that means that the user is an email/password user. So if it's otherwise, we assume that it's a Facebook user. Calling the logout() method in Auth and FacebookAuth clears out the current user of the app. 

Running the App on a Device

Now we can try out our app! First, set up the platform and build the debug apk:

For the Facebook login to work, you need to supply the hash of the apk file to the Facebook app. You can determine the hash by executing the following command:

Next, go to your Facebook app basic settings page and click on the Add Platform button in the bottom part of the screen. Select Android as the platform. You'll then see the following form:

Android platform settings

Fill out the Google Play Package Name and Key Hashes. You can put anything you want as the value for the Google Play Package Name as long as it follows the same format as the apps in Google Play (e.g. com.ionicframework.authapp316678). For the Key Hashes, you need to put in the hash returned from earlier. Don't forget to hit Save Changes when you're done.

Once that's done, you can now copy the android-debug.apk from the platforms/android/build/outputs/apk folder to your device, install it, and then run.

Conclusion and Next Steps

That's it! In this tutorial, you've learned how to make use of the Ionic Auth service to easily implement authentication in your Ionic app. We've used email/password authentication and Facebook login in this tutorial, but there are other options, and it should be easy for you to add those to your app as well. 

Here are some next steps you could try on your own that would take your app to the next level. 

  • Store additional user information—aside from the email and password, you can also store additional information for your users.
  • Use other social login providers—as mentioned at the beginning of the article, you can also implement social login with the following services: Google, Twitter, Instagram, LinkedIn, and GitHub.
  • Add a password reset functionalitypassword resets can be implemented using Ionic's password reset forms, or you can create your own.
  • Custom authentication—if you already have an existing back-end which handles the user authentication for your service, you might need to implement custom authentication.

That's all for now. Stay tuned for more articles on using Ionic services! And in the meantime, check out some of our other great posts on cross-platform mobile app development.

2017-05-22T15:00:00.000Z2017-05-22T15:00:00.000ZWernher-Bel Ancheta

SpriteKit Basics: Sprites

$
0
0

In this series, we're learning how to use SpriteKit to build 2D games for iOS. In this post, we'll continue our exploration of SpriteKit nodes, and learn about a special kind of node called a "sprite"—an SKSpriteNode.

To follow along with this tutorial, just download the accompanying GitHub repo. It has a folder called ExampleProject Starter. Open the project in that folder in Xcode, and you're ready to go!

Sprite Nodes

An SKSpriteNode is drawn either as a rectangle with a texture mapped onto it, or as a colored untextured rectangle. Creating a SKSpriteNode with a texture mapped onto it is the most common, as this is how you bring your game's artwork to life.

Add the following to the didMove(to:) method within GameScene.swift.

Here we are using the convenience intiailizer init(color:size:) which will draw a rectangular sprite with the color and size you pass in as parameters. If you test the project now, you will see half of the red square showing.

red sprite

You might be wondering why only half of the sprite is showing since we already determined that SKNode's origins are at (0,0). This because the SKSpriteNode's frame and therefore its texture is centered on its position. To change this behaviour, you can change the sprite's anchorPoint property, which determines the point at which the frame is positioned. The diagram below shows how the anchorPoint works.

Diagram showing the anchorPoint property within a coordinate system

The anchorPoint is specified in the unit coordinate system, which places (0,0) at the bottom left and (1,1) at the top right corner of the frame. The default for SKSpriteNodes is (0.5,0.5).

Go ahead and change the anchorPoint property to (0,0) and notice the difference it makes.

Now, if you test, you will see that the sprite is lined up perfectly with the bottom left of the scene.

red sprite aligned bottom left

Now let's move it to the top center of the scene by changing its position property. Replace your didMove(to:) function with the following:

Notice how we had to subtract from both the x and y values to center the sprite. If we had left the anchorPoint at its default then it would already have been centered on the x axis. It is important to remember that when you change the anchor point, you may have to make some adjustments in your positioning.

red sprite centered top

Textured Sprites

That red box is good for practice with positioning, but you'll usually want to texture your sprite with artwork for your game. 

Let's create a textured SKSpriteNode. Add the following code at the bottom of the didMove(to:) method.

Here we use the convenience initializer init(imageNamed:), which takes as a parameter the name of an image without the extension. This is the easiest way to create a textured sprite as it creates the texture for you from the image you pass in. 

The other way to create a textured SKSpriteNode is to create an SKTexture beforehand, and use one of the intializers that take a texture as a parameter.

textured sprite

Let's create a couple more SKSpriteNodes and change some of their properties. Again, add these to the bottom of your didMove(to:) function.

Here we create two SKSpriteNodes, enemy1 and enemy2. We set the xScale on enemy1 to 2 and change the zRotation on enemy2 to rotate it by 90 degrees. (The zRotation property takes it values in radians, and a positive value indicates a counterclockwise rotation.) 

We've experimented with changing a few properties on a sprite. Take a look at the documentation for SKNodes and SKSpriteNodes and try changing a few of the other properties to see the effects they have.

textured sprite properties changed

Sprite nodes are good for basic rectangles and textures, but sometimes a more complex shape will be needed. The SKShapeNode has you covered in those cases. We'll take a look at shape nodes next.

Shape Nodes

Another useful node is the SKShapeNode. This node renders a shape defined by a Core Graphics path. SKShapeNodes are useful for content that cannot be easily realized with an SKSpriteNode. This class is more memory intensive and has lower performance than using an SKSpriteNode, so you should try to use it sparingly.

To assign a shape to SKShapeNode, you can set a CGPath to the node's path property. However, there are a few initializers that offer predefined shapes such as rectangles, circles, and ellipses. Let's create a circle using the convenience initializer init(circleOfRadius:).

Then, add the following to the bottom of the didMove(to:) method.

We change a few properties on the shape node, position it, and add it to the scene. It is very easy to use the predefined shape initializers. However, creating a complex CGPath manually takes a considerable amount of time and is not for the faint of heart as it usually involves some complex math. 

Thankfully, there is a tool that lets you draw shapes visually and export their CGPath as Swift code. Check out PaintCode if you want to learn more.

shape node

Sprite Nodes and Shape Nodes will cover most cases, but sometimes you may wish to display video in your apps. The SKVideoNode, which we'll take a look at next, has you covered.

Video Nodes

The last node we will be taking a look at is the SKVideoNode. As the name implies, this node allows you to play video within your games.

There are a few different ways to create an SKVideoNode. One uses an instance of an AVPlayer, another just uses the name of a video file that is stored in the app bundle, and the third way is to use a URL.

One thing to keep in mind is that the video's size property will initially be the same as the size of the target video. You can change this size property, though, and the video will be stretched to the new size.

Another thing to be aware of is that the SKVideoNode offers play() and pause() methods only. If you wanted more control over your videos, you would initialize an SKVideoNode with an existing AVPlayer and use that to control your videos.

Let's use the simplest method to create an SKVideoNode. Add the following to the bottom of the didMove(to:) method.

Here we used the intiailizer init(fileNamed:) to create a video. You pass in the video's name along with the extension. I have not included a video along with the project's source code, but if you want to see this work, you can add a video named "video.mov" to your project.

Conclusion

This completes our study on nodes. After reading this post and the previous one, you should have a good understanding of SKNodes and their subclasses. In the next part of this series, we will take a look at SKActions and using physics within our games. Thanks for reading, and I will see you there!

In the meantime, check out some of our other great courses and tutorials on creating iOS apps with Swift and SpriteKit.

Also, check out our SpriteKit courses! These will take you through all the steps of building your first SpriteKit game for iOS, even if you've never coded with SpriteKit before.

 
2017-05-23T12:00:00.000Z2017-05-23T12:00:00.000ZJames Tyner

Learn the Steps for Creating an Android App in Our New Course

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

Ready to create an Android app? Not so fast. Before you even start building your app, there are a lot of questions to answer. Who is it for? What will the revenue model be? Do other apps exist that already solve this problem? 

Ad revenue for an Android app

In our latest ten-minute Coffee Break Course, Steps to Creating an Android App, Envato Tuts+ instructor Paul Trebilcox-Ruiz will walk you through some of the decisions that need to be made before starting an app project. 

Chromecast

After that, you'll go on to learn about some of the other decisions and tasks that come up during the lifecycle of every app project, such as: 

  • design
  • coding
  • testing
  • publishing
  • revision

Watch the introduction below to find out more.

 

You can take our new Coffee Break Course straight away with a free 10-day trial of our monthly subscription. If you decide to continue, it costs just $15 a month, and you’ll get access to hundreds of courses, with new ones added every week.

And if you need a head start, consider downloading one of the full-featured Android app templates from Envato Market.

2017-05-08T14:35:23.000Z2017-05-08T14:35:23.000ZAndrew Blackman

SpriteKit Basics: Sprites

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

In this series, we're learning how to use SpriteKit to build 2D games for iOS. In this post, we'll continue our exploration of SpriteKit nodes, and learn about a special kind of node called a "sprite"—an SKSpriteNode.

To follow along with this tutorial, just download the accompanying GitHub repo. It has a folder called ExampleProject Starter. Open the project in that folder in Xcode, and you're ready to go!

Sprite Nodes

An SKSpriteNode is drawn either as a rectangle with a texture mapped onto it, or as a colored untextured rectangle. Creating a SKSpriteNode with a texture mapped onto it is the most common, as this is how you bring your game's artwork to life.

Add the following to the didMove(to:) method within GameScene.swift.

Here we are using the convenience intiailizer init(color:size:) which will draw a rectangular sprite with the color and size you pass in as parameters. If you test the project now, you will see half of the red square showing.

red sprite

You might be wondering why only half of the sprite is showing since we already determined that SKNode's origins are at (0,0). This because the SKSpriteNode's frame and therefore its texture is centered on its position. To change this behaviour, you can change the sprite's anchorPoint property, which determines the point at which the frame is positioned. The diagram below shows how the anchorPoint works.

Diagram showing the anchorPoint property within a coordinate system

The anchorPoint is specified in the unit coordinate system, which places (0,0) at the bottom left and (1,1) at the top right corner of the frame. The default for SKSpriteNodes is (0.5,0.5).

Go ahead and change the anchorPoint property to (0,0) and notice the difference it makes.

Now, if you test, you will see that the sprite is lined up perfectly with the bottom left of the scene.

red sprite aligned bottom left

Now let's move it to the top center of the scene by changing its position property. Replace your didMove(to:) function with the following:

Notice how we had to subtract from both the x and y values to center the sprite. If we had left the anchorPoint at its default then it would already have been centered on the x axis. It is important to remember that when you change the anchor point, you may have to make some adjustments in your positioning.

red sprite centered top

Textured Sprites

That red box is good for practice with positioning, but you'll usually want to texture your sprite with artwork for your game. 

Let's create a textured SKSpriteNode. Add the following code at the bottom of the didMove(to:) method.

Here we use the convenience initializer init(imageNamed:), which takes as a parameter the name of an image without the extension. This is the easiest way to create a textured sprite as it creates the texture for you from the image you pass in. 

The other way to create a textured SKSpriteNode is to create an SKTexture beforehand, and use one of the intializers that take a texture as a parameter.

textured sprite

Let's create a couple more SKSpriteNodes and change some of their properties. Again, add these to the bottom of your didMove(to:) function.

Here we create two SKSpriteNodes, enemy1 and enemy2. We set the xScale on enemy1 to 2 and change the zRotation on enemy2 to rotate it by 90 degrees. (The zRotation property takes it values in radians, and a positive value indicates a counterclockwise rotation.) 

We've experimented with changing a few properties on a sprite. Take a look at the documentation for SKNodes and SKSpriteNodes and try changing a few of the other properties to see the effects they have.

textured sprite properties changed

Sprite nodes are good for basic rectangles and textures, but sometimes a more complex shape will be needed. The SKShapeNode has you covered in those cases. We'll take a look at shape nodes next.

Shape Nodes

Another useful node is the SKShapeNode. This node renders a shape defined by a Core Graphics path. SKShapeNodes are useful for content that cannot be easily realized with an SKSpriteNode. This class is more memory intensive and has lower performance than using an SKSpriteNode, so you should try to use it sparingly.

To assign a shape to SKShapeNode, you can set a CGPath to the node's path property. However, there are a few initializers that offer predefined shapes such as rectangles, circles, and ellipses. Let's create a circle using the convenience initializer init(circleOfRadius:).

Then, add the following to the bottom of the didMove(to:) method.

We change a few properties on the shape node, position it, and add it to the scene. It is very easy to use the predefined shape initializers. However, creating a complex CGPath manually takes a considerable amount of time and is not for the faint of heart as it usually involves some complex math. 

Thankfully, there is a tool that lets you draw shapes visually and export their CGPath as Swift code. Check out PaintCode if you want to learn more.

shape node

Sprite Nodes and Shape Nodes will cover most cases, but sometimes you may wish to display video in your apps. The SKVideoNode, which we'll take a look at next, has you covered.

Video Nodes

The last node we will be taking a look at is the SKVideoNode. As the name implies, this node allows you to play video within your games.

There are a few different ways to create an SKVideoNode. One uses an instance of an AVPlayer, another just uses the name of a video file that is stored in the app bundle, and the third way is to use a URL.

One thing to keep in mind is that the video's size property will initially be the same as the size of the target video. You can change this size property, though, and the video will be stretched to the new size.

Another thing to be aware of is that the SKVideoNode offers play() and pause() methods only. If you wanted more control over your videos, you would initialize an SKVideoNode with an existing AVPlayer and use that to control your videos.

Let's use the simplest method to create an SKVideoNode. Add the following to the bottom of the didMove(to:) method.

Here we used the intiailizer init(fileNamed:) to create a video. You pass in the video's name along with the extension. I have not included a video along with the project's source code, but if you want to see this work, you can add a video named "video.mov" to your project.

Conclusion

This completes our study on nodes. After reading this post and the previous one, you should have a good understanding of SKNodes and their subclasses. In the next part of this series, we will take a look at SKActions and using physics within our games. Thanks for reading, and I will see you there!

In the meantime, check out some of our other great courses and tutorials on creating iOS apps with Swift and SpriteKit.

Also, check out our SpriteKit courses! These will take you through all the steps of building your first SpriteKit game for iOS, even if you've never coded with SpriteKit before.

 
2017-05-23T12:00:00.000Z2017-05-23T12:00:00.000ZJames Tyner

Create an Intelligent App With Google Cloud Speech and Natural Language APIs

$
0
0

An application that truly understands a natural language is something sci-fi enthusiasts, programmers, and AI researchers have dreamed about for decades. Today, thanks to large advances in machine learning technologies, that dream is closer than ever to becoming a reality. What's more, cloud-based services such as Google Cloud Machine Learning have made those technologies freely available for everyone to use.

In this tutorial, you'll learn how to use two powerful natural language-oriented APIs offered by the Google Cloud Machine Learning platform: Cloud Speech API and Cloud Natural Language API. By using them together, you can create apps that can handle speech in a variety of widely spoken languages.

Prerequisites

To follow along, you'll need:

1. Why Use These APIs?

An application that can process speech must have the following capabilities:

  • It must be able to extract individual words from raw audio data.
  • It must be able to make educated guesses about the grammatical relationships between the words it has extracted.

The Cloud Speech and Cloud Natural Language APIs enable you to add the above capabilities to your Android app in a matter of minutes.

The Cloud Speech API serves as a state-of-the-art speech recognizer that can accurately transcribe speech in over 80 languages. It can also robustly handle regional accents and noisy conditions.

On a similar note, the Cloud Natural Language API is a language processing system that can, with near-human level accuracy, determine the roles words play in sentences given to it. It currently supports ten languages, and it also offers entity and sentiment analysis.

2. Enabling the APIs

Before you use the Speech and Natural Language APIs, you must enable them in the Google Cloud console. So log in to the console and navigate to API Manager > Library.

Cloud console library

To enable the Speech API, click on the Speech API link in the Google Cloud Machine Learning section. In the page that opens next, press the Enable button.

Enabling Cloud Speech API

Press your browser's back button to return to the previous page.

This time, enable the Natural Language API by clicking on the Natural Language API link and pressing the Enable button on the next page.

Enabling Cloud Natural Language API

You'll need an API key while interacting with the APIs. If you don't have one already, open the Credentials tab, press the Create credentials button, and choose API key.

You'll now see a pop-up displaying your API key. Note it down so you can use it later.

API key generated

3. Configuring Your Project

Both the APIs are JSON-based and have REST endpoints you can interact with directly using any networking library. However, you can save a lot of time—and also write more readable code—by using the Google API Client libraries available for them. So open the build.gradle file of your project's app module and add the following compile dependencies to it:

Additionally, we'll be performing a few file I/O operations in this tutorial. To simplify them, add a compile dependency for the Commons IO library.

Lastly, don't forget to request for the INTERNET permission in the AndroidManifest.xml file. Without it, your app won't be able to connect to Google's servers.

4. Using the Cloud Speech API

It goes without saying that the Cloud Speech API expects audio data as one of its inputs. Therefore, we'll now be creating an Android app that can transcribe audio files. 

To keep it simple, we'll only be transcribing FLAC files, files that use the Free Lossless Audio Codec encoding format. You might already have such files on your device. If you don't, I suggest you download a few from Wikimedia Commons.

Step 1: Create a Layout

Our app's layout will have a Button widget users can press to display a file picker, an interface where they can browse through and select audio files available on their devices.

The layout will also have a TextView widget to display the transcript of the selected audio file. Accordingly, add the following code to your activity's layout XML file:

Step 2: Create a File Picker

The file picker interface should be displayed when the user presses the button we created in the previous step, so associate an OnClickListener object with it. Before you do so, make sure you initialize the button using the findViewById() method.

With Android's Storage Access Framework, which is available on devices running API level 19 or higher, creating a file picker takes very little effort. All you need to do is create an intent for the ACTION_GET_CONTENT action and pass it to the startActivityForResult() method. Optionally, you can restrict the file picker to display only FLAC files by passing the appropriate MIME type to the setType() method of the Intent object.

The output of the file picker will be another Intent object containing the URI of the file the user selected. To be able to access it, you must override the onActivityResult() method of your Activity class.

Step 3: Encode the File

The Cloud Speech API expects its audio data to be in the form of a Base64 string. To generate such a string, you can read the contents of the file the user selected into a byte array and pass it to the encodeBase64String() utility method offered by the Google API Client library.

However, you currently have only the URI of the selected file, not its absolute path. That means that, to be able to read the file, you must resolve the URI first. You can do so by passing it to the openInputStream() method of your activity's content resolver. Once you have access to the input stream of the file, you can simply pass it to the toByteArray() method of the IOUtils class to convert it into an array of bytes. The following code shows you how:

As you can see in the above code, we are using a new thread to run all the I/O operations. Doing so is important in order to make sure that the app's UI doesn't freeze.

Step 4: Play the File

In my opinion, playing the sound file that is being transcribed, while it is being transcribed, is a good idea. It doesn't take much effort, and it improves the user experience.

You can use the MediaPlayer class to play the sound file. Once you point it to the URI of the file using its setDataSource() method, you must call its prepare() method to synchronously prepare the player. When the player is ready, you can call its start() method to start playing the file.

Additionally, you must remember to release the player's resources once it has completed playing the file. To do so, assign an OnCompletionListener object to it and call its release() method. The following code shows you how:

Step 5: Synchronously Transcribe the File

At this point, we can send the Base64-encoded audio data to the Cloud Speech API to transcribe it. But first, I suggest that you store the API key you generated earlier as a member variable of your Activity class.

To be able to communicate with the Cloud Speech API, you must create a Speech object using a Speech.Builder instance. As arguments, its constructor expects an HTTP transport and a JSON factory. Additionally, to make sure that the API key is included in every HTTP request to the API, you must associate a SpeechRequestInitializer object with the builder and pass the key to it.

The following code creates a Speech object using the AndroidJsonFactory class as the JSON factory and the NetHttpTransport class as the HTTP transport:

The Cloud Speech API must be told what language the audio file contains. You can do so by creating a RecognitionConfig object and calling its setLanguageCode() method. Here's how you configure it to transcribe American English only:

Additionally, the Base64-encoded string must be wrapped in a RecognitionAudio object before it can be used by the API.

Next, using the RecognitionConfig and RecognitionAudio objects, you must create a SyncRecognizeRequest object. As its name suggests, it allows you to create an HTTP request to synchronously transcribe audio data. Once the object has been created, you can pass it as an argument to the syncrecognize() method and call the resulting Speech.SpeechOperations.Syncrecognize object's execute() method to actually execute the HTTP request.

The return value of the execute() method is a SyncRecognizeResponse object, which may contain several alternative transcripts. For now, we'll be using the first alternative only.

Finally, to display the transcript to the user, you can pass it to the TextView widget. Of course, because changes to the user interface must always happen on the UI thread, make sure you do so after calling your activity's runOnUiThread() method.

You can now run your app, select a FLAC file containing speech in American English, and see the Cloud Speech API generate a transcript for it.

 

It's worth mentioning that the Cloud Speech API can currently process only single-channel audio files. If you send a file with multiple channels to it, you will get an error response.

5. Using the Cloud Natural Language API

Now that we have a transcript, we can pass it to the Cloud Natural Language API to analyze it. To keep this tutorial short, we'll only be running entity and sentiment analysis on the transcript. In other words, we are going to determine all the entities that are mentioned in the transcript, such as people, places, and professions, and also tell if its overall sentiment is negative, neutral, or positive.

Step 1: Update the Layout

To allow the user to start the analysis, our layout must contain another Button widget. Therefore, add the following code to your activity's layout XML file:

Step 2: Annotate the Transcript

The Cloud Natural Language REST API offers a convenience option called annotateText that allows you to run both sentiment and entity analysis on a document with just one HTTP request. We'll be using it to analyze our transcript.

Because the analysis must begin when the user presses the button we created in the previous step, add an OnClickListener to it.

To interact with the API using the Google API Client library, you must create a CloudNaturalLanguage object using the CloudNaturalLanguage.Builder class. Its constructor also expects an HTTP transport and a JSON factory.

Furthermore, by assigning a CloudNaturalLanguageRequestInitializer instance to it, you can force it to include your API key in all its requests.

All the text you want to analyze using the API must be placed inside a Document object. The Document object must also contain configuration information, such as the language of the text and whether it is formatted as plain text or HTML. Accordingly, add the following code:

Next, you must create a Features object specifying the features you are interested in analyzing. The following code shows you how to create a Features object that says you want to extract entities and run sentiment analysis only.

You can now use the Document and Features objects to compose an AnnotateTextRequest object, which can be passed to the annotateText() method to generate an AnnotateTextResponse object.

Note that we are generating the response in a new thread because network operations aren't allowed on the UI thread.

You can extract a list of entities from the AnnotateTextResponse object by calling its getEntities() method. Similarly, you can extract the overall sentiment of the transcript by calling the getDocumentSentiment() method. To get the actual score of the sentiment, however, you must also call the getScore() method, which returns a float

As you might expect, a sentiment score equal to zero means the sentiment is neutral, a score greater than zero means the sentiment is positive, and a score less than zero means the sentiment is negative.

What you do with the list of entities and the sentiment score is, of course, up to you. For now, let's just display them both using an AlertDialog instance.

With the above code, the sentiment score will be displayed in the title of the dialog, and the list of entities will be displayed in its body.

If you run the app now, you should be able to analyze the content of audio files, as well as transcribing them.

 

Conclusion

You now know how to use the Cloud Speech and Cloud Natural Language APIs together to create an Android app that can not only transcribe an audio file but also run entity and sentiment analysis on it. In this tutorial, you also learned how to work with Android's Storage Access Framework and Google Client API libraries.

Google has been regularly adding new and interesting features—along with support for more languages—to both the APIs. To stay updated about them, do refer to the official documentation.

And while you're here, check out some of our other posts on mobile app cloud services and machine learning!

2017-05-26T12:47:32.000Z2017-05-26T12:47:32.000ZAshraff Hathibelagal

Create an Intelligent App With Google Cloud Speech and Natural Language APIs

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

An application that truly understands a natural language is something sci-fi enthusiasts, programmers, and AI researchers have dreamed about for decades. Today, thanks to large advances in machine learning technologies, that dream is closer than ever to becoming a reality. What's more, cloud-based services such as Google Cloud Machine Learning have made those technologies freely available for everyone to use.

In this tutorial, you'll learn how to use two powerful natural language-oriented APIs offered by the Google Cloud Machine Learning platform: Cloud Speech API and Cloud Natural Language API. By using them together, you can create apps that can handle speech in a variety of widely spoken languages.

Prerequisites

To follow along, you'll need:

1. Why Use These APIs?

An application that can process speech must have the following capabilities:

  • It must be able to extract individual words from raw audio data.
  • It must be able to make educated guesses about the grammatical relationships between the words it has extracted.

The Cloud Speech and Cloud Natural Language APIs enable you to add the above capabilities to your Android app in a matter of minutes.

The Cloud Speech API serves as a state-of-the-art speech recognizer that can accurately transcribe speech in over 80 languages. It can also robustly handle regional accents and noisy conditions.

On a similar note, the Cloud Natural Language API is a language processing system that can, with near-human level accuracy, determine the roles words play in sentences given to it. It currently supports ten languages, and it also offers entity and sentiment analysis.

2. Enabling the APIs

Before you use the Speech and Natural Language APIs, you must enable them in the Google Cloud console. So log in to the console and navigate to API Manager > Library.

Cloud console library

To enable the Speech API, click on the Speech API link in the Google Cloud Machine Learning section. In the page that opens next, press the Enable button.

Enabling Cloud Speech API

Press your browser's back button to return to the previous page.

This time, enable the Natural Language API by clicking on the Natural Language API link and pressing the Enable button on the next page.

Enabling Cloud Natural Language API

You'll need an API key while interacting with the APIs. If you don't have one already, open the Credentials tab, press the Create credentials button, and choose API key.

You'll now see a pop-up displaying your API key. Note it down so you can use it later.

API key generated

3. Configuring Your Project

Both the APIs are JSON-based and have REST endpoints you can interact with directly using any networking library. However, you can save a lot of time—and also write more readable code—by using the Google API Client libraries available for them. So open the build.gradle file of your project's app module and add the following compile dependencies to it:

Additionally, we'll be performing a few file I/O operations in this tutorial. To simplify them, add a compile dependency for the Commons IO library.

Lastly, don't forget to request for the INTERNET permission in the AndroidManifest.xml file. Without it, your app won't be able to connect to Google's servers.

4. Using the Cloud Speech API

It goes without saying that the Cloud Speech API expects audio data as one of its inputs. Therefore, we'll now be creating an Android app that can transcribe audio files. 

To keep it simple, we'll only be transcribing FLAC files, files that use the Free Lossless Audio Codec encoding format. You might already have such files on your device. If you don't, I suggest you download a few from Wikimedia Commons.

Step 1: Create a Layout

Our app's layout will have a Button widget users can press to display a file picker, an interface where they can browse through and select audio files available on their devices.

The layout will also have a TextView widget to display the transcript of the selected audio file. Accordingly, add the following code to your activity's layout XML file:

Step 2: Create a File Picker

The file picker interface should be displayed when the user presses the button we created in the previous step, so associate an OnClickListener object with it. Before you do so, make sure you initialize the button using the findViewById() method.

With Android's Storage Access Framework, which is available on devices running API level 19 or higher, creating a file picker takes very little effort. All you need to do is create an intent for the ACTION_GET_CONTENT action and pass it to the startActivityForResult() method. Optionally, you can restrict the file picker to display only FLAC files by passing the appropriate MIME type to the setType() method of the Intent object.

The output of the file picker will be another Intent object containing the URI of the file the user selected. To be able to access it, you must override the onActivityResult() method of your Activity class.

Step 3: Encode the File

The Cloud Speech API expects its audio data to be in the form of a Base64 string. To generate such a string, you can read the contents of the file the user selected into a byte array and pass it to the encodeBase64String() utility method offered by the Google API Client library.

However, you currently have only the URI of the selected file, not its absolute path. That means that, to be able to read the file, you must resolve the URI first. You can do so by passing it to the openInputStream() method of your activity's content resolver. Once you have access to the input stream of the file, you can simply pass it to the toByteArray() method of the IOUtils class to convert it into an array of bytes. The following code shows you how:

As you can see in the above code, we are using a new thread to run all the I/O operations. Doing so is important in order to make sure that the app's UI doesn't freeze.

Step 4: Play the File

In my opinion, playing the sound file that is being transcribed, while it is being transcribed, is a good idea. It doesn't take much effort, and it improves the user experience.

You can use the MediaPlayer class to play the sound file. Once you point it to the URI of the file using its setDataSource() method, you must call its prepare() method to synchronously prepare the player. When the player is ready, you can call its start() method to start playing the file.

Additionally, you must remember to release the player's resources once it has completed playing the file. To do so, assign an OnCompletionListener object to it and call its release() method. The following code shows you how:

Step 5: Synchronously Transcribe the File

At this point, we can send the Base64-encoded audio data to the Cloud Speech API to transcribe it. But first, I suggest that you store the API key you generated earlier as a member variable of your Activity class.

To be able to communicate with the Cloud Speech API, you must create a Speech object using a Speech.Builder instance. As arguments, its constructor expects an HTTP transport and a JSON factory. Additionally, to make sure that the API key is included in every HTTP request to the API, you must associate a SpeechRequestInitializer object with the builder and pass the key to it.

The following code creates a Speech object using the AndroidJsonFactory class as the JSON factory and the NetHttpTransport class as the HTTP transport:

The Cloud Speech API must be told what language the audio file contains. You can do so by creating a RecognitionConfig object and calling its setLanguageCode() method. Here's how you configure it to transcribe American English only:

Additionally, the Base64-encoded string must be wrapped in a RecognitionAudio object before it can be used by the API.

Next, using the RecognitionConfig and RecognitionAudio objects, you must create a SyncRecognizeRequest object. As its name suggests, it allows you to create an HTTP request to synchronously transcribe audio data. Once the object has been created, you can pass it as an argument to the syncrecognize() method and call the resulting Speech.SpeechOperations.Syncrecognize object's execute() method to actually execute the HTTP request.

The return value of the execute() method is a SyncRecognizeResponse object, which may contain several alternative transcripts. For now, we'll be using the first alternative only.

Finally, to display the transcript to the user, you can pass it to the TextView widget. Of course, because changes to the user interface must always happen on the UI thread, make sure you do so after calling your activity's runOnUiThread() method.

You can now run your app, select a FLAC file containing speech in American English, and see the Cloud Speech API generate a transcript for it.

 

It's worth mentioning that the Cloud Speech API can currently process only single-channel audio files. If you send a file with multiple channels to it, you will get an error response.

5. Using the Cloud Natural Language API

Now that we have a transcript, we can pass it to the Cloud Natural Language API to analyze it. To keep this tutorial short, we'll only be running entity and sentiment analysis on the transcript. In other words, we are going to determine all the entities that are mentioned in the transcript, such as people, places, and professions, and also tell if its overall sentiment is negative, neutral, or positive.

Step 1: Update the Layout

To allow the user to start the analysis, our layout must contain another Button widget. Therefore, add the following code to your activity's layout XML file:

Step 2: Annotate the Transcript

The Cloud Natural Language REST API offers a convenience option called annotateText that allows you to run both sentiment and entity analysis on a document with just one HTTP request. We'll be using it to analyze our transcript.

Because the analysis must begin when the user presses the button we created in the previous step, add an OnClickListener to it.

To interact with the API using the Google API Client library, you must create a CloudNaturalLanguage object using the CloudNaturalLanguage.Builder class. Its constructor also expects an HTTP transport and a JSON factory.

Furthermore, by assigning a CloudNaturalLanguageRequestInitializer instance to it, you can force it to include your API key in all its requests.

All the text you want to analyze using the API must be placed inside a Document object. The Document object must also contain configuration information, such as the language of the text and whether it is formatted as plain text or HTML. Accordingly, add the following code:

Next, you must create a Features object specifying the features you are interested in analyzing. The following code shows you how to create a Features object that says you want to extract entities and run sentiment analysis only.

You can now use the Document and Features objects to compose an AnnotateTextRequest object, which can be passed to the annotateText() method to generate an AnnotateTextResponse object.

Note that we are generating the response in a new thread because network operations aren't allowed on the UI thread.

You can extract a list of entities from the AnnotateTextResponse object by calling its getEntities() method. Similarly, you can extract the overall sentiment of the transcript by calling the getDocumentSentiment() method. To get the actual score of the sentiment, however, you must also call the getScore() method, which returns a float

As you might expect, a sentiment score equal to zero means the sentiment is neutral, a score greater than zero means the sentiment is positive, and a score less than zero means the sentiment is negative.

What you do with the list of entities and the sentiment score is, of course, up to you. For now, let's just display them both using an AlertDialog instance.

With the above code, the sentiment score will be displayed in the title of the dialog, and the list of entities will be displayed in its body.

If you run the app now, you should be able to analyze the content of audio files, as well as transcribing them.

 

Conclusion

You now know how to use the Cloud Speech and Cloud Natural Language APIs together to create an Android app that can not only transcribe an audio file but also run entity and sentiment analysis on it. In this tutorial, you also learned how to work with Android's Storage Access Framework and Google Client API libraries.

Google has been regularly adding new and interesting features—along with support for more languages—to both the APIs. To stay updated about them, do refer to the official documentation.

And while you're here, check out some of our other posts on mobile app cloud services and machine learning!

2017-05-26T12:47:32.000Z2017-05-26T12:47:32.000ZAshraff Hathibelagal

Get Started With Ionic Services: Push

$
0
0

In this tutorial, you're going to learn about Ionic Push, an Ionic service which makes it easy to send push notifications to your users.

Ionic Push allows you to send push notifications to the users of your app. These can be triggered whenever you choose. For example, when it's the user's birthday, you could automatically send them a push notification to greet them. 

How It Works

Ionic Push serves as a middle-man between the user's device and the Firebase Cloud Messaging. The first step is for the app to send its device token to the Ionic Push server. This device token serves as an ID which refers to that specific device. Once the server has that token, they can now make a request to the Firebase Cloud Messaging server to actually send a push notification to the device. On each Android device, a Google Play service is running, called the Google Cloud Messaging service. This enables the device to receive push notifications from the Firebase Cloud Messaging platform.

Here's a chart that shows the push notification flow:

Push notification flow

What You're Going to Build

You're going to build a simple app which can receive push notifications via Ionic Push. It will also use the Ionic Auth service to log users in. This allows us to try out targeted push notifications which will send the notifications to specific users only. The app will have two pages: the login page and the user page. Users should only be able to receive notifications when they are logged in.

To give you an idea how the notifications would look, here's a screenshot of the notification being received while the app is currently open:

in-app notification

On the other hand, here's what a notification looks like when the app is closed:

closed-app notification

Setting Up Push Notifications for Android

In this section, we will configure the Firebase and Ionic cloud services to allow push notifications. Push notifications in Android are mainly handled by the Firebase Cloud Messaging Service. Ionic Push is just a layer on top of this service that makes it easier to work with push notifications in Ionic apps. 

Create a Firebase App

The first step is to create a new Firebase project. You can do that by going to the Firebase Console and clicking on the Add project button. You'll see the following form:

Create Firebase Project

Enter the name of the project and click on the Create Project button.

Once the project is created, you will be redirected to the project dashboard. From there, click on the gear icon right beside the Overview tab and select Project Settings.

On the settings page, click on the Cloud Messaging tab. There you will find the Server Key and Sender ID. Take note of these as you will need them later on.

Cloud messaging settings

Create an Ionic App

Next, you need to create an Ionic app on the Ionic website. This allows you to work with the Ionic Push service and other Ionic services as well. If you don't already have an Ionic account, you can create one by signing up. Once you've created an account, you'll be redirected to the dashboard where you can create a new app. 

Create Ionic App

Create a Security Profile

Once your app is created, go to Settings >Certificates and click on the New Security Profile button. Enter a descriptive name for the Profile Name and set the Type to Development for now:

Create new security profile

Security Profiles serves as a way to securely store the Firebase Cloud Messaging credentials that you got earlier. Once it's created, it will be listed in a table. Click on the Edit button beside the newly created security profile. Then click on the Android tab. Paste the value for the Server Key that you got earlier from the Firebase console into the FCM Server Key field. Finally, click on Save to save the changes.

Add Firebase Cloud Messaging credentials

Bootstrapping a New Ionic App

Create a new Ionic 2 project using the blank template:

Once the project is created, install the phonegap-plugin-push plugin. Supply the Sender ID that you got from the Firebase console earlier:

Next, you need to install the Ionic Cloud plugin. This makes it easy to work with Ionic services inside the app:

Lastly, you need to update the Ionic config files so that Ionic knows that this specific project should be assigned to the Ionic app that you created earlier. You can do that by copying the app ID in your Ionic app's dashboard page. You can find the app ID right below the name of the app. Once you've copied it, open the .io-config.json and ionic.config.json files and paste the value for the app_id.

Building the App

Now you're ready to build the app. The first thing that you need to do is to fire up the Ionic development server so that you can immediately see the changes as you develop the app:

Once the compilation process is done, access the development URL on your browser.

Add Ionic App and Push Settings

Open the src/app/app.module.ts file and add the settings for the app (core) and push notifications (push). The app_id is the ID of the Ionic app that you created earlier. The sender_id is the sender ID that you got earlier from the Firebase console. Under the pluginConfig object, you can optionally set push notification settings. Below we're only setting the sound and vibrate settings to true to tell the hardware that it can play push notification sounds or vibrate if the device is on silent mode. If you want to know more about what configuration options are available, check out the docs on the Push Notification options for Android.

Next, let Ionic know that you want to use the cloudSettings:

Home Page

The default home page in the blank template will serve as the login page. Open the pages/home/home.html file and add the following:

To keep things simple, we only have a login button instead of a full-blown login form. This means that the credentials that we're going to use for logging in are embedded in the code itself.

Next, open the src/pages/home/home.ts file and add the following:

Breaking down the code above, first we import the controllers needed for working with navigation, loaders, and alerts:

Then import the services needed for working with Push and Auth.

Once those are added, import the User page. Comment it out for now as we haven't created that page yet. Don't forget to uncomment this later once the user page is ready.

In the constructor, check if the current user is authenticated. Immediately navigate to the user page if they are:

For the login function, show the loader and set it to automatically dismiss after 5 seconds. This way if something goes wrong with the authentication code, the user isn't left with an infinite loading animation:

After that, log the user in with the hard-coded credentials of a user that's already added in your app:

If you don't have an existing user yet, the Ionic dashboard doesn't really allow you to create new users, although you can create additional users once you already have at least one user. So the easiest way to create a new user is to call the signup() method from the Auth service. Just uncomment the login code above and replace it with the one below. Take note that you can create the user from the browser since the email/password authentication scheme just makes use of HTTP requests.

Now that you have a user that you can log in, you can go ahead and remove the signup code and uncomment the login code. 

Inside the success callback function for login, you need to call the register() method from the Push service. This crucial step enables the device to receive push notifications. It makes a request to the Ionic Push service to get a device token. As mentioned in the How It Works section earlier, this device token serves as a unique identifier for the device so that it can receive push notifications. 

The great thing about Ionic Push is its integration with Ionic Auth. The reason why we're registering the device tokens right after logging in is because of this integration. When you call the saveToken() method, it's smart enough to recognize that a user is currently logged in. So it automatically assigns this user to the device. This then allows you to specifically send a push notification to that user.

User Page

The user page is the page which receives push notifications. Create it with the Ionic generate command:

This will create the src/pages/user-page directory with three files in it. Open the user-page.html file and add the following:

To keep things simple, all we have is a button for logging the user out. The main purpose of this page is to receive and display push notifications only. The logout button is simply added because of the need to log the user out and test if they could still receive notifications after logging out. 

Next, open the user-page.ts file and add the following:

The code above is pretty self-explanatory, so I'll only go over the part which deals with notifications. The code below handles the notifications. It uses the subscribe() method to subscribe for any incoming or opened push notification. When I say "opened", it means the user has tapped on the notification in the notifications area. When this happens, the app is launched, and the callback function that you passed to the subscribe() method gets called. On the other hand, an incoming push notification happens when the app is currently opened. When a push notification is sent, this callback function also gets called. The only difference is that it no longer goes to the notification area.

For each notification, the argument passed to the callback function contains the object payload:

Push notification payload

In the above code, we're only using the title and the text to supply as the content for the alert. We're not limited to just alerts, though—as you can see from the screenshot above, there's this payload object which stores additional data that you want to pass in to each notification. You can actually use these data to direct what your app is going to do when it receives this kind of notification. In the example above, is_cat is set to 1, and we can have the app change its background into a cat picture if it receives this notification. Later on in the Sending Push Notifications section, you'll learn how to customize the payload for each notification.

Running the App on a Device

Now it's time to test out the app on a device. Go ahead and add the platform and build the app for that platform. Here we're using Android:

Copy the .apk file inside the platforms/android/build/outputs/apk folder to your device and install it.

Solving Build Errors

The first time I tried to run the build command, I got the following error:

Android build error

If you got the same error then follow along. If you haven't encountered any errors then you can proceed to the next section.

The problem here is that the SDK components mentioned were not installed, or there might be an important update that needs to be installed. However, the error message is a bit misleading, since it only says that the license agreement needs to be accepted.

So to solve the problem, launch the Android SDK installer and then check the Android Support Repository and Google Repository. After that, click on the Install button and agree to the license agreement to install the components.

Sending Push Notifications

Now that you've installed the app on your device, it's now time to actually send some push notifications. Here are a few scenarios which you can test out:

  • when a user isn't currently logged in
  • when a user is logged in
  • to all users
  • to users which match a specific query
  • when the app is opened
  • when the app is closed

The first step in sending a push notification is to go to your Ionic app dashboard and click on the Push tab. Since this is your first time using the service, you should see the following screen:

create your first push

Go ahead and click on the Create your first Push button. This will redirect you to the page for creating a push notification. Here you can enter the name of the campaign, title and text of the notification, and any additional data that you want to pass in. Here we're setting is_cat to 1.

push details

Next, you can optionally set the push notification options for iOS or Android. Since we're only going to send to Android devices, we only set the options for Android:

android push options

The next step is to select the users who will receive the notification. Here you can select All Users if you want to send the notification to all the devices which are registered for push notifications. 

Select users to push to

If you only want to send to specific users then you can also filter to them:

push to selected users

Take note that the users list is populated from users that are registered via the Auth service.

The final step is to select when to send the notification. Since we're only testing, we can send it immediately. Clicking on the Send This Push button will send the notification to your selected users.

Schedule push

Conclusion and Next Steps

In this tutorial, you've learned about Ionic Push and how it makes push notifications easier to implement. Through the Ionic dashboard, you were able to customize the notifications that you're sending to users. It also allows you to select which users you want to send the notifications to. 

This works great if you don't have an existing back end already. But if you already have a back end, you might be asking how you can use Ionic Push with your existing web application. Well, the answer for that is the Ionic HTTP API. This allows you to send an HTTP request from your web server to Ionic's server whenever a specific condition is met. The request that you send will then trigger a push notification to be sent to your users. If you want to learn more, you can check out the docs for the Ionic Push Service.

And while you're here, check out some of our other courses and tutorials on Ionic 2!

2017-05-29T13:55:34.000Z2017-05-29T13:55:34.000ZWernher-Bel Ancheta

Get Started With Ionic Services: Push

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

In this tutorial, you're going to learn about Ionic Push, an Ionic service which makes it easy to send push notifications to your users.

Ionic Push allows you to send push notifications to the users of your app. These can be triggered whenever you choose. For example, when it's the user's birthday, you could automatically send them a push notification to greet them. 

How It Works

Ionic Push serves as a middle-man between the user's device and the Firebase Cloud Messaging. The first step is for the app to send its device token to the Ionic Push server. This device token serves as an ID which refers to that specific device. Once the server has that token, they can now make a request to the Firebase Cloud Messaging server to actually send a push notification to the device. On each Android device, a Google Play service is running, called the Google Cloud Messaging service. This enables the device to receive push notifications from the Firebase Cloud Messaging platform.

Here's a chart that shows the push notification flow:

Push notification flow

What You're Going to Build

You're going to build a simple app which can receive push notifications via Ionic Push. It will also use the Ionic Auth service to log users in. This allows us to try out targeted push notifications which will send the notifications to specific users only. The app will have two pages: the login page and the user page. Users should only be able to receive notifications when they are logged in.

To give you an idea how the notifications would look, here's a screenshot of the notification being received while the app is currently open:

in-app notification

On the other hand, here's what a notification looks like when the app is closed:

closed-app notification

Setting Up Push Notifications for Android

In this section, we will configure the Firebase and Ionic cloud services to allow push notifications. Push notifications in Android are mainly handled by the Firebase Cloud Messaging Service. Ionic Push is just a layer on top of this service that makes it easier to work with push notifications in Ionic apps. 

Create a Firebase App

The first step is to create a new Firebase project. You can do that by going to the Firebase Console and clicking on the Add project button. You'll see the following form:

Create Firebase Project

Enter the name of the project and click on the Create Project button.

Once the project is created, you will be redirected to the project dashboard. From there, click on the gear icon right beside the Overview tab and select Project Settings.

On the settings page, click on the Cloud Messaging tab. There you will find the Server Key and Sender ID. Take note of these as you will need them later on.

Cloud messaging settings

Create an Ionic App

Next, you need to create an Ionic app on the Ionic website. This allows you to work with the Ionic Push service and other Ionic services as well. If you don't already have an Ionic account, you can create one by signing up. Once you've created an account, you'll be redirected to the dashboard where you can create a new app. 

Create Ionic App

Create a Security Profile

Once your app is created, go to Settings >Certificates and click on the New Security Profile button. Enter a descriptive name for the Profile Name and set the Type to Development for now:

Create new security profile

Security Profiles serves as a way to securely store the Firebase Cloud Messaging credentials that you got earlier. Once it's created, it will be listed in a table. Click on the Edit button beside the newly created security profile. Then click on the Android tab. Paste the value for the Server Key that you got earlier from the Firebase console into the FCM Server Key field. Finally, click on Save to save the changes.

Add Firebase Cloud Messaging credentials

Bootstrapping a New Ionic App

Create a new Ionic 2 project using the blank template:

Once the project is created, install the phonegap-plugin-push plugin. Supply the Sender ID that you got from the Firebase console earlier:

Next, you need to install the Ionic Cloud plugin. This makes it easy to work with Ionic services inside the app:

Lastly, you need to update the Ionic config files so that Ionic knows that this specific project should be assigned to the Ionic app that you created earlier. You can do that by copying the app ID in your Ionic app's dashboard page. You can find the app ID right below the name of the app. Once you've copied it, open the .io-config.json and ionic.config.json files and paste the value for the app_id.

Building the App

Now you're ready to build the app. The first thing that you need to do is to fire up the Ionic development server so that you can immediately see the changes as you develop the app:

Once the compilation process is done, access the development URL on your browser.

Add Ionic App and Push Settings

Open the src/app/app.module.ts file and add the settings for the app (core) and push notifications (push). The app_id is the ID of the Ionic app that you created earlier. The sender_id is the sender ID that you got earlier from the Firebase console. Under the pluginConfig object, you can optionally set push notification settings. Below we're only setting the sound and vibrate settings to true to tell the hardware that it can play push notification sounds or vibrate if the device is on silent mode. If you want to know more about what configuration options are available, check out the docs on the Push Notification options for Android.

Next, let Ionic know that you want to use the cloudSettings:

Home Page

The default home page in the blank template will serve as the login page. Open the pages/home/home.html file and add the following:

To keep things simple, we only have a login button instead of a full-blown login form. This means that the credentials that we're going to use for logging in are embedded in the code itself.

Next, open the src/pages/home/home.ts file and add the following:

Breaking down the code above, first we import the controllers needed for working with navigation, loaders, and alerts:

Then import the services needed for working with Push and Auth.

Once those are added, import the User page. Comment it out for now as we haven't created that page yet. Don't forget to uncomment this later once the user page is ready.

In the constructor, check if the current user is authenticated. Immediately navigate to the user page if they are:

For the login function, show the loader and set it to automatically dismiss after 5 seconds. This way if something goes wrong with the authentication code, the user isn't left with an infinite loading animation:

After that, log the user in with the hard-coded credentials of a user that's already added in your app:

If you don't have an existing user yet, the Ionic dashboard doesn't really allow you to create new users, although you can create additional users once you already have at least one user. So the easiest way to create a new user is to call the signup() method from the Auth service. Just uncomment the login code above and replace it with the one below. Take note that you can create the user from the browser since the email/password authentication scheme just makes use of HTTP requests.

Now that you have a user that you can log in, you can go ahead and remove the signup code and uncomment the login code. 

Inside the success callback function for login, you need to call the register() method from the Push service. This crucial step enables the device to receive push notifications. It makes a request to the Ionic Push service to get a device token. As mentioned in the How It Works section earlier, this device token serves as a unique identifier for the device so that it can receive push notifications. 

The great thing about Ionic Push is its integration with Ionic Auth. The reason why we're registering the device tokens right after logging in is because of this integration. When you call the saveToken() method, it's smart enough to recognize that a user is currently logged in. So it automatically assigns this user to the device. This then allows you to specifically send a push notification to that user.

User Page

The user page is the page which receives push notifications. Create it with the Ionic generate command:

This will create the src/pages/user-page directory with three files in it. Open the user-page.html file and add the following:

To keep things simple, all we have is a button for logging the user out. The main purpose of this page is to receive and display push notifications only. The logout button is simply added because of the need to log the user out and test if they could still receive notifications after logging out. 

Next, open the user-page.ts file and add the following:

The code above is pretty self-explanatory, so I'll only go over the part which deals with notifications. The code below handles the notifications. It uses the subscribe() method to subscribe for any incoming or opened push notification. When I say "opened", it means the user has tapped on the notification in the notifications area. When this happens, the app is launched, and the callback function that you passed to the subscribe() method gets called. On the other hand, an incoming push notification happens when the app is currently opened. When a push notification is sent, this callback function also gets called. The only difference is that it no longer goes to the notification area.

For each notification, the argument passed to the callback function contains the object payload:

Push notification payload

In the above code, we're only using the title and the text to supply as the content for the alert. We're not limited to just alerts, though—as you can see from the screenshot above, there's this payload object which stores additional data that you want to pass in to each notification. You can actually use these data to direct what your app is going to do when it receives this kind of notification. In the example above, is_cat is set to 1, and we can have the app change its background into a cat picture if it receives this notification. Later on in the Sending Push Notifications section, you'll learn how to customize the payload for each notification.

Running the App on a Device

Now it's time to test out the app on a device. Go ahead and add the platform and build the app for that platform. Here we're using Android:

Copy the .apk file inside the platforms/android/build/outputs/apk folder to your device and install it.

Solving Build Errors

The first time I tried to run the build command, I got the following error:

Android build error

If you got the same error then follow along. If you haven't encountered any errors then you can proceed to the next section.

The problem here is that the SDK components mentioned were not installed, or there might be an important update that needs to be installed. However, the error message is a bit misleading, since it only says that the license agreement needs to be accepted.

So to solve the problem, launch the Android SDK installer and then check the Android Support Repository and Google Repository. After that, click on the Install button and agree to the license agreement to install the components.

Sending Push Notifications

Now that you've installed the app on your device, it's now time to actually send some push notifications. Here are a few scenarios which you can test out:

  • when a user isn't currently logged in
  • when a user is logged in
  • to all users
  • to users which match a specific query
  • when the app is opened
  • when the app is closed

The first step in sending a push notification is to go to your Ionic app dashboard and click on the Push tab. Since this is your first time using the service, you should see the following screen:

create your first push

Go ahead and click on the Create your first Push button. This will redirect you to the page for creating a push notification. Here you can enter the name of the campaign, title and text of the notification, and any additional data that you want to pass in. Here we're setting is_cat to 1.

push details

Next, you can optionally set the push notification options for iOS or Android. Since we're only going to send to Android devices, we only set the options for Android:

android push options

The next step is to select the users who will receive the notification. Here you can select All Users if you want to send the notification to all the devices which are registered for push notifications. 

Select users to push to

If you only want to send to specific users then you can also filter to them:

push to selected users

Take note that the users list is populated from users that are registered via the Auth service.

The final step is to select when to send the notification. Since we're only testing, we can send it immediately. Clicking on the Send This Push button will send the notification to your selected users.

Schedule push

Conclusion and Next Steps

In this tutorial, you've learned about Ionic Push and how it makes push notifications easier to implement. Through the Ionic dashboard, you were able to customize the notifications that you're sending to users. It also allows you to select which users you want to send the notifications to. 

This works great if you don't have an existing back end already. But if you already have a back end, you might be asking how you can use Ionic Push with your existing web application. Well, the answer for that is the Ionic HTTP API. This allows you to send an HTTP request from your web server to Ionic's server whenever a specific condition is met. The request that you send will then trigger a push notification to be sent to your users. If you want to learn more, you can check out the docs for the Ionic Push Service.

And while you're here, check out some of our other courses and tutorials on Ionic 2!

2017-05-29T13:55:34.000Z2017-05-29T13:55:34.000ZWernher-Bel Ancheta

Ensure High-Quality Android Code With Static Analysis Tools

$
0
0

In today's tutorial, we'll learn about how to ensure high-quality Android code in our projects using some static code analysis tools for Java. We'll look at Checkstyle, FindBugs, PMD, and Android Studio Lint—all of them free and open source!

What Are Static Code Analysis Tools?

These are tools that parse and analyse your source code without actually executing it. The goal is to find potential vulnerabilities such as bugs and security flaws. A popular free static code analyser such as FindBugs checks your code against a set of rules which your code should adhere to—if the code doesn't follow these rules, it's a sign that something may be wrong. Think of static code analysis tools as an additional compiler that is run before the final compilation into the system language.  

Many software companies are requiring projects to pass static code analysis tests, in addition to doing code reviews and unit testing in the build process. Even maintainers of open-source projects often include one or more static code analysis steps in the build process. So learning about static analysis is an important step in writing quality code. Be aware that static code analysis—also known as "white-box" testing—should not be seen as a replacement for unit testing of your source code.

In this tutorial, we're going to learn about some popular static analysis tools that are available for Android and Java. But first, let's see some of the benefits of using static analysis.

Benefits

  • Helps detect potential bugs that even unit or manual testing might have missed.
  • Defines project-specific rules. For example, static analysis as part of the build chain helps newcomers get up to speed with the code standards of their new team.
  • Helps you improve your knowledge of a new language.
  • Scans your whole project, including files that you might not have ever read.

Setup

All the code analysis tools we'll learn about in this tutorial are available as Gradle plugins, so we can create individual Gradle tasks for each of them. Let's use a single Gradle file that will include them all. But before that, let's create a folder that will contain all of our files for the static code analysis. 

Open Android Studio and inside the app module (in Project view), create a new folder and name it code_quality_tools. This folder will contain the XML files for the code analysis tools, and it will also have a Gradle file, quality.gradle, which will run our static analysis tasks. 

Android studio project structure screenshot

Finally, visit your build.gradle in the app module folder and include this line at the end of the file:

Here, our quality.gradle Gradle script is being applied with a reference to its local file location. 

Checkstyle

Given rules you specify in an XML file to enforce a coding standard for your project, Checkstyle enforces those rules by analysing your source code and compares them against known coding standards or conventions. 

Checkstyle is an open-source tool that is actively maintained by the community. This means you can create your own custom checks or modify existing ones to suit your needs. For example, Checkstyle can run a check on the constant names (final, static, or both) in your classes. If your constant names do not stick to a rule of being in uppercase with words separated by an underscore, the problem will be flagged in the final report. 

Integrating Checkstyle

I'll show you how to integrate Checkstyle into our Android Studio project and demonstrate a practical example.

First, we need to create our coding rules. Inside checkstyle.xml, we create some Checkstyle configuration rules that will be run against our code.

In the above code, we include the rules or checks we want Checkstyle to validate in our source code. One rule is AvoidStarImport which, as the name says, checks if your source code included an import statement like java.util.*. (Instead, you should explicitly specify the package to import, e.g. java.util.Observable.) 

Some rules have properties, which we can set just like we did for ParameterNumber—this limits the number of parameters of a method or constructor. By default, the property max is 7, but we changed it to 6 instead. Take a look at some of the other checks on the Checkstyle website.

To run this check, we need to create a Gradle task. So visit the quality.gradle file and create a task called checkstyle:

Notice that in the code above, we first applied the Checkstyle Gradle plugin. We gave it a description and added it to an already predefined Gradle group called verification. 

The key properties of the Checkstyle Gradle task we are concerned with are: 

  • configFile: the Checkstyle configuration file to use.
  • IgnoreFailures: whether or not to allow the build to continue if there are warnings.
  • include: the set of include patterns.
  • exclude: the set of exclude patterns. In this case, we don't scan generated classes. 

Finally, you can run the Gradle script by visiting the Gradle tool window on Android Studio, opening the verification group, and then clicking on checkstyle to run the task. 

Gradle toolbar open to run checkstyle task

Another way is to use the command line: 

After the task has finished running, a report will be generated, which is available at app module > build > reports > checkstyle. You can open checkstyle.html to view the report. 

Android Studio Checkstyle report folder location

Checkstyle plugin is freely available for Android Studio or IntelliJ IDEA. It offers real-time scanning of your Java files. 

PMD

PMD is another open-source code analysis tool that analyzes your source code. It finds common flaws like unused variables, empty catch blocks, unnecessary object creation and so on. PMD has many rule sets you can choose from. An example of a rule which is part of the Design Rules set is:

  • SimplifyBooleanExpressions: avoid unnecessary comparisons in boolean expressions which complicate simple code. An example: 

PMD is configured with the pmd.xml file. Inside it, we'll include some configuration rules such as the ones for Android, Naming, and Design

As we did for Checkstyle, we also need to create a PMD Gradle task for the check to be executed inside the quality.gradle file. 

PMD is also available as a Gradle plugin

The key properties of the task we've created are: 

  • ruleSetFiles: The custom rule set files to be used.
  • source: The source for this task.
  • reports: The reports to be generated by this task.

Finally, you can run the Gradle script by visiting the Gradle tool window, opening the verification group folder, and then clicking on pmd to run the task. Or you can run it via the command line:

A report will also be generated after the execution of the task which is available at app module > build > reports > pmd. There is also a PMD plugin available for IntelliJ or Android Studio for you to download and integrate if you want. 

FindBugs

FindBugs is another free static analysis tool which analyses your class looking for potential problems by checking your bytecodes against a known list of bug patterns. Some of them are:

  • Class defines hashCode() but not equals(): A class implements the hashCode() method but not equals()—therefore two instances might be equal but not have the same hash codes. This falls under the bad practice category. 
  • Bad comparison of int value with long constant: The code is comparing an int value with a long constant that is outside the range of values that can be represented as an int value. This comparison is vacuous and possibly will yield an unexpected result. This falls under the correctness category. 
  • TestCase has no tests: class is a JUnit TestCase but has not implemented any test methods. This pattern is also under the correctness category. 

FindBugs is an open-source project, so you can view, contribute or monitor the progress of the source code on GitHub

In the findbugs-exclude.xml file, we want to prevent FindBugs from scanning some classes (using regular expressions) in our projects, such as auto-generated resource classes and auto-generated manifest classes. Also, if you use Dagger, we want FindBugs not to check the generated Dagger classes. We can also tell FindBugs to ignore some rules if we want. 

And finally, we'll include the findbugs task in quality.gradle:

In the first line above, we applied FindBugs as a Gradle Plugin and then created a task called findbugs. The key properties of the findbugs task we are really concerned with are: 

  • classes: the classes to be analyzed.
  • effort: the analysis effort level. The value specified should be one of mindefault, or max.  Be aware that higher levels increase precision and find more bugs at the cost of running time and memory consumption.
  • reportLevel: the priority threshold for reporting bugs. If set to low, all bugs are reported. If set to medium (the default), medium and high priority bugs are reported. If set to high, only high priority bugs are reported.
  • excludeFilter: the filename of a filter specifying bugs to exclude from being reported, which we have created already. 

You can then run the Gradle script by visiting the Gradle tool window, opening the verification group folder, and then clicking on findbugs to run the task. Or launch it from the command line:

A report will also be generated when the task has finished executing. This will be available at app module > build > reports > findbugs. The FindBugs plugin is another freely available plugin for download and integration with either IntelliJ IDEA or Android Studio.

Android Lint

Lint is another code analysis tool, but this one comes with Android Studio by default. It checks your Android project source files for potential bugs and optimizations for correctness, security, performance, usability, accessibility, and internationalization. 

To configure Lint, you have to include the lintOptions {} block in your module-level build.gradle file:

The key Lint options we are concerned with are: 

  • abortOnError: whether lint should set the exit code of the process if errors are found.
  • quiet: whether to turn off analysis progress reporting.
  • lintConfig: the default configuration file to use.

Your lint.xml file can include issues you want Lint to ignore or modify, such as the example below:

You can run Lint manually from Android Studio by clicking on the Analyze menu, choosing Inspect Code... (the inspection scope is the whole project), and then clicking on the OK button to proceed.

Android studio inspect code menu
Android Studio lint inspect whole project code dialog

You can also run Lint by visiting the Gradle tool window, opening the verification group, and then clicking on lint. Finally, you can run it via the command line.

On Windows:

On Linux or Mac:

A report will also be generated when the task has finished executing, which is available at app module > build > outputs > lint-results.html.

Bonus: StrictMode

StrictMode is a developer tool that helps prevent developers of your project doing any accidental flash I/O or network I/O on the main thread, because this can lead to the app being sluggish or unresponsive. It also helps in preventing ANR (App Not Responding) dialogs from showing up. With StrictMode issues corrected, your app will become more responsive and the user will enjoy a smoother experience. StrictMode uses two sets of policies to enforce its rules:

  • VM Policies: guards against bad coding practices such as not closing SQLiteCursor objects or any Closeable object that was created. 
  • Thread Policies: looks out for operations such as flash I/O and network I/O being performed on the main application thread instead of on a background thread. 

The code above can be either in your Application, Activity, or other application component's onCreate() method. 

You can learn more about StrictMode here on Envato Tuts+. 

A sample Android project implementing all of the above including rule sets of the tools for a typical Android project can be found in this post's GitHub repo.

Conclusion

In this tutorial, you learned about how to ensure high-quality Android code using static code analysis tools: what they are, benefits of using them, and how to use Checkstyle, FindBugs, Lint, PMD, and StrictMode in your application. Go ahead and give these tools a try—you might discover some problems in your code that you never expected.

In the meantime, check out some of our other courses and tutorials on Android app development!

2017-05-30T18:59:57.000Z2017-05-30T18:59:57.000ZChike Mgbemena
Viewing all 1836 articles
Browse latest View live