Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Save more on your purchases! discount-offer-chevron-icon
Savings automatically calculated. No voucher code required.
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Newsletter Hub
Free Learning
Arrow right icon
timer SALE ENDS IN
0 Days
:
00 Hours
:
00 Minutes
:
00 Seconds

How-To Tutorials - Mobile

213 Articles
article-image-working-xamarinandroid
Packt
03 Nov 2015
10 min read
Save for later

Working with Xamarin.Android

Packt
03 Nov 2015
10 min read
In this article written by Matthew Leibowitz, author of the book Xamarin Mobile Development for Android Cookbook, wants us to learn about the Android version that can be used as support for your project. (For more resources related to this topic, see here.) Supporting all Android versions As the Android operating system evolves, many new features are added and older devices are often left behind. How to do it... In order to add the new features of the later versions of Android to the older versions of Android, all we need to do is add a small package: An Android app has three platform versions to be set. The first is the API features that are available to code against. We set this to always be the latest in the Target Framework dropdown of the project options. The next version to set (via Minimum Android version) is the lowest version of the OS that the app can be installed on. When using the support libraries, we can usually target versions down to version 2.3. Lastly, the Target Android version dropdown specifies how the app should behave when installed on a later version of the OS. Typically, this should always be the latest so that the app will always function as the user expects. If we want to add support for the new UI paradigm that uses fragments and action bars, we need to install two of the Android support packages: Create or open a project in Xamarin Studio. Right-click on the project folder in the Solution Explorer list. Select Add and then Add Packages…. In the Add Packages dialog that is displayed, search for Xamarin.Android.Support. Select both Xamarin Support Library v4 and Xamarin Support Library v7 AppCompat. Click on Add Package. There are several support library packages, each adding other types of forward compatibility, but these two are the most commonly used. Once the packages are installed, our activities can inherit from the AppCompatActivity type instead of the usual Activity type: public class MyActivity : AppCompatActivity { } We specify that the activity theme be one of the AppCompat derivatives using the Theme property in the [Activity] attribute: [Activity(..., Theme = "@style/Theme.AppCompat", ...)] If we need to access the ActionBar instance, it is available via the SupportActionBar property on the activity: SupportActionBar.Title = "Xamarin Cookbook"; By simply using the action bar, all the options menu items are added as action items. However, all of them are added under the action bar overflow menu: The XML for action bar items is exactly the same as the options menu: <menu ... >   <item     android_id="@+id/action_refresh"     android_icon="@drawable/ic_action_refresh"     android_title="@string/action_refresh"/> </menu> To get the menu items out of the overflow and onto the actual action bar, we can customize the items to be displayed and how they are displayed: To add action items with images to the actual action bar as well as more complex items, all that is needed is an attribute in the XML, showAsAction: <menu ... >   <item ... app_showAsAction="ifRoom"/> </menu> Sometimes, we may wish to only display the icon initially and then, when the user taps the icon, expand the item to display the action view: <menu ... >   <item ... app_showAsAction="ifRoom|collapseActionView"/> </menu> If we wish to add custom views, such as a search box, to the action bar, we make use of the actionViewClass attribute: <menu ... >   <item ...   app_actionViewClass="android.support.v7.widget.SearchView"/> </menu> If the view is in a layout resource file, we use the actionLayout attribute: <menu ... >   <item ... app_actionLayout="@layout/action_rating"/> </menu> How it works... As Android is developed, new features are added and designs change. We want to always provide the latest features to our users, but some users either haven't upgraded or can't upgrade to the latest version of Android. Xamarin.Android provides three version numbers to specify which types can be used and how they can be used. The target framework version specifies what types are available for consumption as well as what toolset to use during compilation. This should be the latest as we always want to use the latest tools. However, this will make some types and members available to apps even if they aren't actually available on the Android version that the user is using. For example, it will make the ActionBar type available to apps running on Android version 2.3. If the user were to run the app, it would probably crash. In these instances, we can set the minimum Android version to be a version that supports these types and members. But, this will then reduce the number of devices that we can install our app on. This is why we use the support libraries; they allow the types to be used on most versions of Android. Setting the minimum Android version for an app will prevent the app from being installed on devices with earlier versions of the OS. The support libraries By including the Android Support Libraries in our app, we can make use of the new features but still support the old versions. Types from the Android Support Library are available to almost all versions of Android currently in use. The Android Support Libraries provide us with a type that we know we can use everywhere, and then that base type manages the features to ensure that they function as expected. For example, we can use the ActionBar type on most versions of Android because the support library made it available through the AppCompatActivity type. Because the AppCompatActivity type is an adaptive extension for the traditional Activity type, we have to use a different theme. This theme adjusts so that the new look and feel of the UI gets carried all the way back to the old Android versions. When using the AppCompatActivity type, the activity theme must be one of the AppCompat theme variations. There are a few differences in the use when using the support library. With native support for the action bar, the AppCompatActivity type has a property named ActionBar; however, in the support library, the property is named SupportActionBar. This is just a property name change but the functionality is the same. Sometimes ,features have to be added to the existing types that are not in the support libraries. In these cases, static methods are provided. The native support for custom views in menu items includes a method named SetActionView(): menuItem.SetActionView(someView); This method does not exist on the IMenuItem type for the older versions of Android, so we make use of the static method on the MenuItemCompat type: MenuItemCompat.SetActionView(menuItem, someView); The action bar While adding an action bar on older Android versions, it is important to inherit it from the AppCompatActivity type. This type includes all the logic required for including an action bar in the app. It also provides many different methods and properties for accessing and configuring the action bar. In newer versions of Android, all the features are included in the Activity type. Although the functionality is the same, we do have to access the various pieces using the support members when using the support libraries. An example would be to use the SupportActionBar property instead of the ActionBar property. If we use the ActionBar property, the app will crash on devices that don't natively support the ActionBar property. In order to render the action bar, the activity needs to use a theme that contains a style for the action bar or one that inherits from such a theme. For the older versions of Android, we can use the AppCompat themes, such as Theme.AppCompat. The toolbar With the release of Android version 5.0, Google introduced a new style of action bar. The new Toolbar type performs the same function as the action bar but can be placed anywhere on the screen. The action bar is always placed at the top of the screen, but a toolbar is not restricted to that location and can even be placed inside other layouts. To make use of the Toolbar type, we can either use the native type, or we can use the type found in the support libraries. Like any Android View, we can add the ToolBar type to the layout: <android.support.v7.widget.Toolbar   android_id="@+id/my_toolbar"   android_layout_width="match_parent"   android_layout_height="?attr/actionBarSize"   android_background="?attr/colorPrimary"   android_elevation="4dp"   android_theme="@style/ThemeOverlay.AppCompat.ActionBar"   app_popupTheme="@style/ThemeOverlay.AppCompat.Light"/> The difference is in how the activity is set up. First, as we are not going to use the default ActionBar property, we can use the Theme.AppCompat.NoActionBar theme. Then, we have to let the activity know which view is used as the Toolbar type: var toolbar = FindViewById<Toolbar>(Resource.Id.toolbar); SetSupportActionBar(toolbar); The action bar items Action item buttons are just traditional options menu items but are optionally always visible on the action bar. The underlying logic to handle item selections is the same as that for the traditional options menu. No change is required to be made to the existing code inside the OnOptionsItemSelected() method. The value of the showAsAction attribute can be ifRoom, never, or always. This value can optionally be combined, using a pipe, with withText and/or collapseActionView. There's more... Besides using the Android Support Libraries to handle different versions, there is another way to handle different versions at runtime. Android provides the version number of the current operating system through the Build.VERSION type. This type has a property, SdkInt, which we use to detect the current version. It represents the current API level of the version. Each version of Android has a series of updates and new features. For example, Android 4 has numerous updates since its initial release, new features being added each time. Sometimes, the support library cannot cover all the cases, and we have to write specific code for particular versions: int apiLevel = (int)Build.VERSION.SdkInt; if (Build.VERSION.SdkInt >= BuildVersionCodes.IceCreamSandwich) {   // Android version 4.0 and above } else {   // Android versions below version 4.0 } Although the preceding can be done, it introduces spaghetti code and should be avoided. In addition to different code, the app may behave differently on different versions, even if the support library could have handled it. We will now have to manage these differences ourselves each time a new version of Android is released. Summary In this article, we learned that as the technology grows, new features are added and released in Android and older devices are often left behind. Thus, using the given steps we can add the new features of the later versions of Android to the older versions of Android, all we need to do is add packages by following the simple steps given in here. Resources for Article: Further resources on this subject: Creating the POI ListView layout [article] Code Sharing Between iOS and Android [article] Heads up to MvvmCross [article]
Read more
  • 0
  • 0
  • 4064

article-image-getting-started-playstation-mobile
Packt
26 Apr 2013
7 min read
Save for later

Getting Started with PlayStation Mobile

Packt
26 Apr 2013
7 min read
(For more resources related to this topic, see here.) The PlayStation Mobile (PSM) SDK represents an exciting opportunity for game developers of all stripes, from hobbyists to indie and professional developers. It contains everything you need to quickly develop a game using the C# programming language. Perhaps more importantly, it provides a market for those games. If you are currently using XNA, you will feel right at home with the PSM SDK. You may be wondering at this point, Why develop for PlayStation Mobile at all? Obviously, the easiest answer is, so you can develop for PlayStation Vita , which of itself will be enough for many people. Perhaps, though the most important reason is that it represents a group of dedicated gamers hungry for games. While there are a wealth of games available for Android, finding them on the App Store is a mess, while supporting the literally thousands of devices is a nightmare. With PlayStation Mobile, you have a common development environment, targeting powerful devices with a dedicated store catering to gamers. We are now going to jump right in and get those tools up and running. Of course, we will also write some code and show how easy it is to get it running on your device. PlayStation Mobile allows you to target a number of different devices and we will cover the three major targets (the Simulator, PlayStation Vita, and Android). You do not need to have a device to follow along, although certain functionality will not be available on the Simulator. One thing to keep in mind with the PlayStation Mobile SDK is that it is essentially two SDKs in one. There is a much lower level set of libraries for accessing graphics, audio, and input, as well as a higher-level layer build over the top of this layer, mostly with the complete source available. Of course, underneath this all there is the .NET framework. In this article, we are going to deal with the lower level graphics interface. If the code seems initially quite long or daunting for what seems like a simple task, don't worry! There is a much easier way that we will cover later in the book. Accessing the PlayStation Mobile portal This recipe looks at creating a PSM portal account. For this process it is mandatory to download and use the PSM SDK. Getting ready You need to have a Sony Entertainment Network (SEN) account to register with the PSM portal. This is the standard account you use to bring your PlayStation device online, so you may already have one. If not, create one at http://bit.ly/Yiglfk before continuing. How to do it... Open a web browser and log in to http://psm.playstation.net. Locate and click on the Register button. Sign in using the SEN account. Agree to the Terms and Conditions. You need to scroll to the bottom of the text before the Agree button is enabled. But, you always read the fine print anyways... don't you? Finally select the e-mail address and language you want for the PlayStation Mobile portal. You can use the same e-mail you used for your SEN account. Click on Register. An e-mail will be sent to the e-mail account you used to sign up. Locate the activation link and either click on it, or copy and paste into a browser window: Your account is now completed, and you can log in to the PSM developer portal now. How it works... A PlayStation Mobile account is mandatory to download the PSM tools. Many of the links to the portal require you to be logged in before they will work. It is very important that you create and activate your account and log in to the portal before continuing on with the book! All future recipes assume you are logged in to the portal. Installing the PlayStation Mobile SDK This recipe demonstrates how to install the PlayStation Mobile SDK. Getting ready First you need to download the PlayStation Mobile SDK; you can download it from http://bit.ly/W8rhhx. How to do it... Locate the installation file you downloaded earlier and double-click to launch the installer. Say yes to any security related questions. Take the default settings when prompting, making sure to install the runtimes and GTK# libraries. The installer for the Vita drivers will now launch. There is no harm in installing them even if you do not have a Vita: Installation is now complete; a browser window with the current release notes will open. How it works... The SDK is now installed on your machines. Assuming you used default directories, the SDK will be installed to C:Program Files (x86)SCEPSM if you are running 64 bit Windows, or to C:Program FilesSCEPSM if you are running 32 bit Windows. Additionally all of the documentation and samples have been installed under the Public account, located in C:UsersPublicDocumentsPSM. There's more... There are a number of samples available in the samples directory and you should certainly take a moment to check them out. They range in complexity from simple Hello World applications, up to a full blown 3rd person 3D role playing game (RPG). They are, however, often documented in Japanese and often rely on other samples, making learning from them a frustrating experience at times, at least, for those of us who do not understand Japanese! Creating a simple game loop We are now going to create our first PSM SDK application, which is the main loop of your application. Actually all the code in this sample is going to be generated by PSM Studio for us. Getting ready From the start menu, locate and launch PSM Studio in the PlayStation Mobile folder. How to do it... In PSM Studio, select the File | New | Solution... menu. In the resulting dialog box, in the left-hand panel expand C# and select PlayStation Suite, then in the right-hand panel, select PlayStation Suite Application. Fill in the Name field, which will automatically populate the Solution name field. Click on OK. Your workspace and boilerplate code will now be created; hit the F5 key or select the Run | Start Debugging menu to run your code in the Simulator. Not much to look at, but it's your first running PlayStation Mobile application! Now let's take a quick look at the code it generated: using System; using System.Collections.Generic; using Sce.PlayStation.Core; using Sce.PlayStation.Core.Environment; using Sce.PlayStation.Core.Graphics; using Sce.PlayStation.Core.Input; namespace Ch1_Example1 { public class AppMain{ private static GraphicsContext graphics; public static void Main (string[] args){ Initialize (); while (true) { SystemEvents.CheckEvents (); Update (); Render (); } } public static void Initialize (){ graphics = new GraphicsContext (); } public static void Update (){ var gamePadData = GamePad.GetData (0); } public static void Render () { graphics.SetClearColor (0.0f, 0.0f, 0.0f, 0.0f); graphics.Clear (); graphics.SwapBuffers (); } } } How it works... This recipe shows us the very basic skeleton of an application. Essentially it loops forever, displaying a black screen. private static GraphicsContext graphics; The GraphicsContext variable represents the underlying OpenGL context. It is used to perform almost every graphically related action. Additionally, it contains the capabilities (resolution, pixel depth, and so on) of the underlying graphics device. All C# based applications have a main function, and this one is no exception. Within Main() we call our Initialize() method, then loop forever, checking for events, updating, and finally rendering the frame. The Initialize() method simply creates a new GraphicsContext variable. The Update() method polls the first gamepad for updates. Finally Render() uses our GraphicsContext variable to first clear the screen to black using an RGBA color value, then clears the screen and swaps the buffers, making it visible. Graphic operations in PSM SDK generally are drawn to a back buffer. There's more... The same process is used to create PlayStation Suite library projects, which will generate a DLL file. You can use almost any C# library that doesn't rely on native code (pInvoke or Unsafe); however, they need to be recompiled into a PSM compatible DLL format. Color in the PSM SDK is normally represented as an RGBA value. The RGBA acronym stands for red, green, blue, and alpha. Each is an int variable type, with values ranging from 0 to 255 representing the strength of each primary color. Alpha represents the level of transparency, with 0 being completely transparent and 256 being opaque.
Read more
  • 0
  • 0
  • 4057

article-image-flash-development-android-audio-input-microphone
Packt
22 Jun 2011
4 min read
Save for later

Flash Development for Android: Audio Input via Microphone

Packt
22 Jun 2011
4 min read
  Flash Development for Android Cookbook Introduction Camera and microphone are standard accessories on most mobile devices and Android devices are no exception to this. In the previous article we dealt with Visual Input via Camera. The present article will cover encoding raw audio captured from the device microphone and encoding it to WAV or MP3 for use on other platforms and systems. All of the recipes in this article are represented as pure ActionScript 3 classes and are not dependent upon external libraries or the Flex framework. Therefore, we will be able to use these examples in any IDE we wish. The reader is advised to refer to the first recipe of Flash Development for Android: Visual Input via Camera for detecting microphone support. Using the device microphone to monitor audio sample data By monitoring the sample data being returned from the Android device microphone through the ActionScript Microphone API, we can gather much information about the sound being captured, and perform responses within our application. Such input can be used in utility applications, learning modules, and even games. How to do it... We will set up an event listener to respond to sample data reported through the Microphone API: First, import the following classes into your project: import flash.display.Sprite; import flash.display.Stage; import flash.display.StageAlign; import flash.display.StageScaleMode; import flash.events.SampleDataEvent; import flash.media.Microphone; import flash.text.TextField; import flash.text.TextFormat; Declare a TextField and TextFormat object pair to allow visible output upon the device. A Microphone object must also be declared for this example: private var mic:Microphone; private var traceField:TextField; private var traceFormat:TextFormat; We will now set up our TextField, apply a TextFormat, and add the TextField to the DisplayList. Here, we create a method to perform all of these actions for us: protected function setupTextField():void { traceFormat = new TextFormat(); traceFormat.bold = true; traceFormat.font = "_sans"; traceFormat.size = 44; traceFormat.align = "center"; traceFormat.color = 0x333333; traceField = new TextField(); traceField.defaultTextFormat = traceFormat; traceField.selectable = false; traceField.mouseEnabled = false; traceField.width = stage.stageWidth; traceField.height = stage.stageHeight; addChild(traceField); } Now, we must instantiate our Microphone object and set it up according to our needs and preferences with adjustments to codec, rate, silenceLevel, and so forth. Here we use setSilenceLevel() to determine what the minimum input level our application should consider to be "sound" and the rate property is set to 44, indicating that we will capture audio data at a rate of 44kHz. Setting the setLoopBack () property to false will keep the captured audio from being routed through the device speaker: protected function setupMic():void { mic = Microphone.getMicrophone(); mic.setSilenceLevel(0); mic.rate = 44; mic.setLoopBack(false); } Once we have instantiated our Microphone object, we can then register a variety of event listeners. In this example, we'll be monitoring audio sample data from the device microphone, so we will need to register our listener for the SampleDataEvent.SAMPLE_DATA constant: protected function registerListeners():void { mic.addEventListener(SampleDataEvent.SAMPLE_DATA, onMicData); } As the Microphone API generates sample data from the Android device input, we can now respond to this in a number of ways, as we have access to information about the Microphone object itself, and more importantly, we have access to the sample bytes with which we can perform a number of advanced operations: public function onMicData(e:SampleDataEvent):void { traceField.text = ""; traceField.appendText("activityLevel: " + e.target.activityLevel + "n"); traceField.appendText("codec: " + e.target.codec + "n"); traceField.appendText("gain: " + e.target.gain + "n"); traceField.appendText("bytesAvailable: " + e.data.bytesAvailable + "n"); traceField.appendText("length: " + e.data.length + "n"); traceField.appendText("position: " + e.data.position + "n"); } The output will look something like this. The first three values are taken from the Microphone itself, the second three from Microphone sample data: How it works... When we instantiate a Microphone object and register a SampleDataEvent.SAMPLE_DATA event listener, we can easily monitor various properties of our Android device microphone and the associated sample data being gathered. We can then respond to that data in many ways. One example would be to move objects across the Stage based upon the Microphone.activityLevel property. Another example would be to write the sample data to a ByteArray for later analysis. What do all these properties mean? activityLevel: This is a measurement indicating the amount of sound being received codec: This indicates the codec being used: Nellymoser or Speex gain: This is an amount of boosting provided by the microphone to the sound signal bytesAvailable: This reveals the number of bytes from the present position until the end of our sample data byteArray length: Lets us know the total length of our sample data byteArray position: This is the current position, in bytes, within our sample data byteArray  
Read more
  • 0
  • 0
  • 4042

article-image-building-mobile-games-craftyjs-and-phonegap-part-3
Robi Sen
13 Jul 2015
9 min read
Save for later

Building Mobile Games with Crafty.js and PhoneGap, Part 3

Robi Sen
13 Jul 2015
9 min read
In this post, we will build upon what we learned in our previous series on using Crafty.js, HTML5, JavaScript, and PhoneGap to make a mobile game. In this post we will add a trigger to call back our monster AI, letting the monsters know it’s their turn to move, so each time the player moves the monsters will also move. Structuring our code with components Before we begin updating our game, let’s clean up our code a little bit. First let’s abstract out some of the code into separate files so it’s easier to work, read, edit, and develop our project. Let’s make a couple of components. The first one will be called PlayerControls.js and will tell the system what direction to move an entity when we touch on the screen. To do this, first create a new directory under your project WWW directory called src. Then create a new directory in src called com . In the folder create a new file called PlayerControls.js. Now open the file and make it look like the following: // create a simple object that describes player movement Crafty.c("PlayerControls", { init: function() { //lets now make the hero move where ever we touch Crafty.addEvent(this, Crafty.stage.elem, 'mousedown', function(e) { // lets simulate a 8 way controller or old school joystick //build out the direction of the mouse point. Remember that y increases as it goes 'downward' if (e.clientX < (player.x+Crafty.viewport.x) && (e.clientX - (player.x+Crafty.viewport.x))< 32) { myx = -1; } else if (e.clientX > (player.x+Crafty.viewport.x) && (e.clientX - (player.x+Crafty.viewport.x)) > 32){ myx = 1; } else { myx = 0; } if (e.clientY < (player.y+Crafty.viewport.y) && (e.clientY - (player.y+Crafty.viewport.y))< 32) { myy= -1; } else if (e.clientY > (player.y+Crafty.viewport.y) && (e.clientY - (player.y+Crafty.viewport.y)) > 32){ myy= 1; } else { myy = 0;} // let the game know we moved and where too var direction = [myx,myy]; this.trigger('Slide',direction); Crafty.trigger('Turn'); lastclientY = e.clientY; lastclientX = e.clientX; console.log("my x direction is " + myx + " my y direction is " + myy) console.log('mousedown at (' + e.clientX + ', ' + e.clientY + ')'); }); } }); You will note that this is very similar to the PlayerControls  component in our current index.html. One of the major differences is now we are decoupling the actual movement of our player from the mouse/touch controls. So if you look at the new PlayerControls component you will notice that all it does is set the X and Y direction, relative to a player object, and pass those directions off to a new component we are going to make called Slide. You will also see that we are using crafty.trigger to trigger an event called turn. Later in our code we are going to detect that trigger to active a callback to our monster AI letting the monsters know it’s their turn to move, so each time the player moves the monsters will also move. So let’s create a new component called Slide.js and it will go in your com directory with PlayerControls.js. Now open the file and make it look like this: Crafty.c("Slide", { init: function() { this._stepFrames = 5; this._tileSize = 32; this._moving = false; this._vx = 0; this._destX = 0; this._sourceX = 0; this._vy = 0; this._destY = 0; this._sourceY = 0; this._frames = 0; this.bind("Slide", function(direction) { // Don't continue to slide if we're already moving if(this._moving) return false; this._moving = true; // Let's keep our pre-movement location this._sourceX = this.x; this._sourceY = this.y; // Figure out our destination this._destX = this.x + direction[0] * 32; this._destY = this.y + direction[1] * 32; // Get our x and y velocity this._vx = direction[0] * this._tileSize / this._stepFrames; this._vy = direction[1] * this._tileSize / this._stepFrames; this._frames = this._stepFrames; }).bind("EnterFrame",function(e) { if(!this._moving) return false; // If we'removing, update our position by our per-frame velocity this.x += this._vx; this.y += this._vy; this._frames--; if(this._frames == 0) { // If we've run out of frames, // move us to our destination to avoid rounding errors. this._moving = false; this.x = this._destX; this.y = this._destY; } this.trigger('Moved', {x: this.x, y: this.y}); }); }, slideFrames: function(frames) { this._stepFrames = frames; }, // A function we'll use later to // cancel our movement and send us back to where we started cancelSlide: function() { this.x = this._sourceX; this.y = this._sourceY; this._moving = false; } }); As you can see, it is pretty straightforward. Basically, it handles movement by accepting a direction as a 0 or 1 within X and Y axis’. It then moves any entity that inherits its behavior some number of pixels; in this case 32, which is the height and width of our floor tiles. Now let’s do a little more housekeeping. Let’s pull out the sprite code in to a Sprites.js file and the asset loading code into a Loading.js  file. So create to new files, Sprites.js and Loading.js respectively, in your com directory and edit them to looking like the following two listings. Sprites.js: Crafty.sprite(32,"assets/dungeon.png", { floor: [0,1], wall1: [18,0], stairs: [3,1] }); // This will create entities called hero1 and blob1 Crafty.sprite(32,"assets/characters.png", { hero: [11,4], goblin1: [8,14] }); Loading.js: Crafty.scene("loading", function() { //console.log("pants") Crafty.load(["assets/dungeon.png","assets/characters.png"], function() { Crafty.scene("main"); // Run the main scene console.log("Done loading"); }, function(e) { //progress }, function(e) { //somethig is wrong, error loading console.log("Error,failed to load", e) }); }); Okay, now that is done let’s redo our index.html to make it cleaner: <!DOCTYPE html> <html> <head></head> <body> <div id="game"></div> <script type="text/javascript" src="lib/crafty.js"></script> <script type="text/javascript" src="src/com/loading.js"></script> <script type="text/javascript" src="src/com/sprites.js"></script> <script type="text/javascript" src="src/com/Slide.js"></script> <script type="text/javascript" src="src/com/PlayerControls.js"></script> <script> // Initialize Crafty Crafty.init(500, 320); // Background Crafty.background('green'); Crafty.scene("main",function() { Crafty.background("#FFF"); player = Crafty.e("2D, Canvas,PlayerControls, Slide, hero") .attr({x:0, y:0}) goblin = Crafty.e("2D, Canvas, goblin1") .attr({x:50, y:50}); }); Crafty.scene("loading"); </script> </body> </html> Go ahead save the file and load it in your browser. Everything should work as expected but now our index file and directory is a lot cleaner and easier to work with. Now that this is done, let’s get to giving the monster the ability to move on its own. Monster fun – moving game agents We are up to the point that we are able to move the hero of our game around the game screen with mouse clicks/touches. Now we need to make things difficult for our hero and make the monster move as well. To do this we need to add a very simple component that will move the monster around after our hero moves. To do this create a file called AI.js in the com directory. Now open it and edit it to look like this:   Crafty.c("AI",{ _directions: [[0,-1], [0,1], [1,0], [-1,0]], init: function() { this._moveChance = 0.5; this.requires('Slide'); this.bind("Turn",function() { if(Math.random() < this._moveChance) { this.trigger("Slide", this._randomDirection()); } }); }, moveChance: function(val) { this._moveChance = val; }, _randomDirection: function() { return this._directions[Math.floor(Math.random()*4)]; } }); As you can see all AI.js does, when called, is feed random directions to slide. Now we will add the AI component to the goblin entity. To do this editing your index.html to look like the following: <!DOCTYPE html> <html> <head></head> <body> <div id="game"></div> <script type="text/javascript" src="lib/crafty.js"></script> <script type="text/javascript" src="src/com/loading.js"></script> <script type="text/javascript" src="src/com/sprites.js"></script> <script type="text/javascript" src="src/com/Slide.js"></script> <script type="text/javascript" src="src/com/AI.js"></script> <script type="text/javascript" src="src/com/PlayerControls.js"></script> <script> Crafty.init(500, 320); Crafty.background('green'); Crafty.scene("main",function() { Crafty.background("#FFF"); player = Crafty.e("2D, Canvas,PlayerControls, Slide, hero") .attr({x:0, y:0}) goblin = Crafty.e("2D, Canvas, AI, Slide, goblin1") .attr({x:50, y:50}); }); Crafty.scene("loading"); </script> </body> </html> Here you will note we added a new entity called goblin and added the components Slide and AI. Now save the file and load it. When you move your hero you should see the goblin move as well like in this screenshot: Summary While this was a long post, you have learned a lot. Now that we have the hero and goblin moving in our game, we will build a dungeon in part 4, enable our hero to fight goblins, and create a PhoneGap build for our game. About the author Robi Sen, CSO at Department 13, is an experienced inventor, serial entrepreneur, and futurist whose dynamic twenty-plus year career in technology, engineering, and research has led him to work on cutting edge projects for DARPA, TSWG, SOCOM, RRTO, NASA, DOE, and the DOD. Robi also has extensive experience in the commercial space, including the co-creation of several successful start-up companies. He has worked with companies such as UnderArmour, Sony, CISCO, IBM, and many others to help build out new products and services. Robi specializes in bringing his unique vision and thought process to difficult and complex problems, allowing companies and organizations to find innovative solutions that they can rapidly operationalize or go to market with.
Read more
  • 0
  • 0
  • 3998

article-image-working-sharing-plugin
Packt
23 May 2014
11 min read
Save for later

Working with the sharing plugin

Packt
23 May 2014
11 min read
(For more resources related to this topic, see here.) Now that we've dealt with the device events, let's get to the real meat of the project: let's add the sharing plugin and see how to use it. Getting ready Before continuing, be sure to add the plugin to your project: cordova plugin add https ://github.com/leecrossley/cordova-plugin-social-message.git Getting on with it This particular plugin is one of many socialnetwork plugins. Each one has its benefits and each one has its problems, and the available plugins are changing rapidly. This particular plugin is very easy to use, and supports a reasonable amount of social networks. On iOS, Facebook, Twitter, Mail, and Flickr are supported. On Android, any installed app that registers with the intent to share is supported. The full documentation is available at https://github.com/leecrossley/cordova-plugin-social-message at the time of writing this. It is easy to follow if you need to know more than what we cover here. To show a sharing sheet (the appearance varies based on platform and operation system), all we have to do is this: window.socialshare.send ( message ); message is an object that contains any of the following properties: text: This is the main content of the message. subject: This is the subject of the message. This is only applicable while sending e-mails; most other social networks will ignore this value. url: This is a link to attach to the message. image: This is an absolute path to the image in order to attach it to the message. It must begin with file:/// and the path should be properly escaped (that is, spaces should become %20, and so on). activityTypes (only for iOS): This supports activities on various social networks. Valid values are: PostToFacebook, PostToTwitter, PostToWeibo, Message, Mail, Print, CopyToPasteboard, AssignToContact, and SaveToCameraRoll. In order to create a simple message to share, we can use the following code: var message = {     text: "something to send" } window.socialshare.send ( message ); To add an image, we can go a step further, shown as follows: var message = {     text: "the caption",     image: "file://var/mobile/…/image.png" } window.socialshare.send ( message ); Once this method is called, the sharing sheet will appear. On iOS 7, you'll see something like the following screenshot: On Android, you will see something like the following screenshot: What did we do? In this section, we installed the sharing plugin and we learned how to use it. In the next sections, we'll cover the modifications required to use this plugin. Modifying the text note edit view We've dispatched most of the typical sections in this project—there's not really any user interface to design, nor are there any changes to the actual note models. All we need to do is modify the HTML template a little to include a share button and add the code to use the plugin. Getting on with it First, let's alter the template in www/html/textNoteEditView.html. I've highlighted the changes: <html>   <body>     <div class="ui-navigation-bar">       <div class="ui-title"         contenteditable="true">%NOTE_NAME%</div>       <div class="ui-bar-button-group ui-align-left">         <div class="ui-bar-button ui-tint-color ui-back-button">%BACK%</div>       </div>       <div class="ui-bar-button-group ui-align-right">         <div class="ui-bar-button ui-destructive-           color">%DELETE_NOTE%</div>       </div>     </div>     <div class="ui-scroll-container ui-avoid-navigation-bar ui-       avoid-tool-bar">       <textarea class="ui-text-box" >%NOTE_CONTENTS%</textarea>     </div><div class="ui-tool-bar"><div class="ui-bar-button-group ui-align-left"></div><div class="ui-bar-button-group ui-align-center">     </div>         <div class="ui-bar-button-group ui-align-right">        <div class="ui-bar-button ui-background-tint-color ui- glyph ui-glyph-share share-button"></div></div>    </div></body></html> Now, let's make the modifications to the view in www/js/app/views/textNoteEditView.js. First, we need to add an internal property that references the share button: self._shareButton = null; Next, we need to add code to renderToElement so that we can add an event handler to the share button. We'll do a little bit of checking here to see if we've found the icon, because we don't support sharing of videos and sounds and we don't include that asset in those views. If we didn't have the null check, those views would fail to work. Consider the following code snippet: self.renderToElement = function () {   …   self._shareButton = self.element.querySelector ( ".share-button"     );   if (self._shareButton !== null) {     Hammer ( self._shareButton ).on("tap", self.shareNote);   }   … } Finally, we need to add the method that actually shares the note. Note that we save the note before we share it, since that's how the data in the DOM gets transmitted to the note model. Consider the following code snippet: self.shareNote = function () {   self.saveNote();   var message = {     subject: self._note.name,     text: self._note.textContents   };   window.socialmessage.send ( message ); } What did we do? First, we added a toolbar to the view that looks like the following screenshot—note the new sharing icon: Then, we added the code that shares the note and attaches that code to the Share button. Here's an example of us sending a tweet from a note on iOS: What else do I need to know? Don't forget that social networks often have size limits. For example, Twitter only supports 140 characters, and so if you send a note using Twitter, it needs to be a very short note. We could, on iOS, prevent Twitter from being permitted, but there's no way to prevent this on Android. Even then, there's no real reason not to prevent Twitter from being an option. The user just needs to be familiar enough with the social network to know that they'll have to edit the content before posting it. Also, don't forget that the subject of a message only applies to mail; most other social networks will ignore it. If something is critical, be sure to include it in the text of the message, and not the subject only. Modifying the image note edit view The image note edit view presents an additional difficulty: we can't put the Share button in a toolbar. This is because doing so will cause positioning difficulties with TEXTAREA and the toolbar when the soft keyboard is visible. Instead, we'll put it in the lower-right corner of the image. This is done by using the same technique we used to outline the camera button. Getting on with it Let's edit the template in www/html/imageNoteEditView.html; again, I've highlighted the changes: <html>   <body>     <div class="ui-navigation-bar">       <div class="ui-title"         contenteditable="true">%NOTE_NAME%</div>       <div class="ui-bar-button-group ui-align-left">         <div class="ui-bar-button ui-tint-color ui-back-           button">%BACK%</div>       </div>       <div class="ui-bar-button-group ui-align-right">         <div class="ui-bar-button ui-destructive-           color">%DELETE_NOTE%</div>       </div>     </div>     <div class="ui-scroll-container ui-avoid-navigation-bar">       <div class="image-container">         <div class="ui-glyph ui-background-tint-color ui-glyphcamera-         outline"></div>               <div class="ui-glyph ui-background-tint-color ui-glyph-           camera outline"></div>         <div class="ui-glyph ui-background-tint-color ui-glyph-           camera non-outline"></div>         <div class="ui-glyph ui-background-tint-color ui-glyph-           share outline"></div>         <div class="ui-glyph ui-background-tint-color ui-glyph-           share non-outline share-button"></div>       </div>       <textarea class="ui-text-box"         onblur="this.classList.remove('editing');"         onfocus="this.classList.add('editing');         ">%NOTE_CONTENTS%</textarea>     </div>   </body> </html> Because sharing an image requires a little additional code, we need to override shareNote (which we inherit from the prior task) in www/js/app/views/imageNoteEditView.js: self.shareNote = function () {   var fm = noteStorageSingleton.fileManager;   var nativePath = fm.getNativeURL ( self._note.mediaContents );   self.saveNote();   var message = {     subject: self._note.name,     text: self._note.textContents   };   if (self._note.unitValue > 0) {     message.image = nativePath;   }   window.socialmessage.send ( message ); } Finally, we need to add the following styles to www/css/style.css: div.ui-glyph.ui-background-tint-color.ui-glyph-share.outline, div.ui-glyph.ui-background-tint-color.ui-glyph-share.non-outline {   left:inherit;   width:50px;   top: inherit;   height:50px; } {   -webkit-mask-position:15px 16px;   mask-position:15px 16px; } div.ui-glyph.ui-background-tint-color.ui-glyph-share.non-outline {   -webkit-mask-position:15px 15px;   mask-position:15px 15px; } What did we do? Like the previous task, we first modified the template to add the share icon. Then, we added the shareNote code to the view (note that we don't have to add anything to find the button, because we inherit it from the Text Note Edit View). Finally, we modify the style sheet to reposition the Share button appropriately so that it looks like the following screenshot: What else do I need to know? The image needs to be a valid image, or the plugin may crash. This is why we check for the value of unitValue in shareNote to ensure that it is large enough to attach to the message. If not, we only share the text. Game Over... Wrapping it up And that's it! You've learned how to respond to device events, and you've also added sharing to text and image notes by using a third-party plugin. Can you take the HEAT? The Hotshot Challenge There are several ways to improve the project. Why don't you try a few? Implement the ability to save the note when the app receives a pause event, and then restore the note when the app is resumed. Remember which note is visible when the app is paused, and restore it when the app is resumed. (Hint: localStorage may come in handy.) Add video or audio sharing. You'll probably have to alter the sharing plugin or find another (or an additional) plugin. You'll probably also need to upload the data to an external server so that it can be linked via the social network. For example, it's often customary to link to a video on Twitter by using a link shortener. The File Transfer plugin might come in handy for this challenge (https://github.com/apache/cordova-plugin-file-transfer/blob/dev/doc/index.md). Summary This article introduced you to a third-party plugin that provides access to e-mail and various social networks. Resources for Article: Further resources on this subject: Geolocation – using PhoneGap features to improve an app's functionality, write once use everywhere [Article] Configuring the ChildBrowser plugin [Article] Using Location Data with PhoneGap [Article]
Read more
  • 0
  • 0
  • 3837

article-image-building-mobile-games-craftyjs-and-phonegap-part-2
Robi Sen
15 May 2015
7 min read
Save for later

Building Mobile Games with Crafty.js and PhoneGap - Part 2

Robi Sen
15 May 2015
7 min read
Building Mobile Games with Crafty.js and PhoneGap - Part 2 Let’s continue making a simple turn-based RPG-like game based on Pascal Rettig’s Crafty Workshop presentation with PhoneGap. In the second part of this two-part series, you will learn how to add sprites to a game, control them, and work with mouse/touch events. Adding sprites OK, let’s add some sprites to the mix using open source sprite sheets from RLTiles. All of the resources at RLTiles are in public domain, but the ones we will need are the dungeon tiles, which you can find here, and the monsters, which you can find here. To use them, first create a new folder under your www root directory in your PhoneGap project called assets. Then, click on the Dungeon link and right-click on the dungeon  sprite sheet and select Save as. Save it as dungeon.png to your assets directory. Do the same with monsters, but call it characters.png.  Now, edit index.html to look like listing 1. Listing 1: Loading sprites in Crafty <!DOCTYPE html> <html> <head></head> <body> <div id="game"></div> <script type="text/javascript" src="lib/crafty.js"></script> <script> var WIDTH = 500, HEIGHT = 320; Crafty.init(WIDTH, HEIGHT); // Background Crafty.background("black"); //let’s loads some assets for the game // This will create entities called floor, wall1, and stairs Crafty.sprite(32,"assets/dungeon.png", { floor: [0,0], wall1: [2,1], stairs: [3,1] }); // This will create entities called hero1 and blob1 Crafty.sprite(32,"assets/characters.png", { hero: [11,4],goblin1: [8,14] }); Crafty.scene("loading", function() { Crafty.load(["assets/dungeon.png","assets/characters.png"], function() { Crafty.scene("main"); // Run the main scene console.log("Done loading"); }, function(e) { //progress }, function(e) { //somethig is wrong, error loading console.log("Error,failed to load", e) }); }); Crafty.scene("loading"); // Let's draw us a Hero and a Goblin Crafty.scene("main",function() { Crafty.background("#FFF"); var player = Crafty.e("2D, Canvas, hero") .attr({x:0, y:0}); var goblin = Crafty.e("2D, Canvas, goblin1") .attr({x:50, y:50}); }); </script> </body> </html> There are a couple of things to note in this code. Firstly, we are using Crafty.sprite to load sprites from a sprite file. The first attribute in the sprite(), 32, references the size of the sprite. The second is the location of the sprite sheet. Next, we set the name of each sprite we want to load and its location. For example, floor(0,0) means grab the very first sprite on the sprite sheet, assign it the label floor, and load it into memory. Next is a very important Crafty function; Crafty.scene(). In Crafty, scenes are a way to organize your game objects and easily transition between levels or screens. In our case, we first use Crafty.scene() to load a bunch of assets, our sprite sheets, and when done, we tell it to call the main() scene. Next, we actually call loading, which loads our assets and then calls the main() scene. In the main() scene, we create the player and goblin entities. Try saving the file and loading it in your browser. You should see something like figure 1.   Figure 1: Loading the hero and goblin sprites in Chrome Movement Now that we have figured out how to load the sprites, let’s figure out how to move them. First, we want to move and control our hero. To do this, we want to make a component, which is an abstracted set of data or behaviors we can then assign to an entity. To do that, open your index.html file again and edit it to look like listing 2. Listing 2: Controlling the hero <!DOCTYPE html> <html> <head></head> <body> <div id="game"></div> <script type="text/javascript" src="lib/crafty.js"></script> <script> var WIDTH = 500, HEIGHT = 320; Crafty.init(WIDTH, HEIGHT); Crafty.sprite(32,"assets/dungeon.png", { floor: [0,0], wall1: [2,1], stairs: [3,1] }); Crafty.sprite(32,"assets/characters.png", { hero: [11,4], goblin1: [8,14] }); // create a simple object that describes player movement Crafty.c("PlayerControls", { init: function() { //let’s now make the hero move wherever we touch Crafty.addEvent(this, Crafty.stage.elem, 'mousedown', function(e) { // let’s simulate an 8-way controller or old school joystick console.log("the values are; x= " + e.clientX ); if (e.clientX<player.x&& (e.clientX - player.x)< 32) {player.x= player.x - 32;} else if (e.clientX>player.x&& (e.clientX - player.x) > 32){ player.x = player.x + 32; } else {player.x = player.x} if (e.clientY<player.y&& (e.clientY - player.y)< 32) {player.y= player.y - 32;} else if (e.clientY>player.y&& (e.clientY - player.y) > 32){ player.y = player.y + 32; } else {player.y = player.y} Crafty.trigger('Turn'); console.log('mousedown at (' + e.clientX + ', ' + e.clientY + ')'); }); } }); Crafty.scene("loading", function() { Crafty.load(["assets/dungeon.png","assets/characters.png"], function() { Crafty.scene("main"); // Run the main scene console.log("Done loading"); }, function(e) { //progress }, function(e) { //somethig is wrong, error loading console.log("Error,failed to load", e) }); }); Crafty.scene("loading"); // Let's draw us a Hero and a mean Goblin Crafty.scene("main",function() { Crafty.background("#FFF"); player = Crafty.e("2D, Canvas,Fourway, PlayerControls, hero") .attr({x:0, y:0}) goblin = Crafty.e("2D, Canvas, goblin1") .attr({x:50, y:50}); }); </script> </body> </html> In listing 2, the main thing to focus on is the PlayerControls component defined by Crafty.c(). In the component, we are going to simulate a typical 8-way controller. For our PlayerControls component, we want the player to only be able to move one tile, which is 32 pixels, each time they select a direction they want to move. We do this by using Crafty.addEvent and having it update the player’s location based on the direction of where the user touched, which is derived by getting the relative location of the user’s touch from client.x, client.y in relation to the hero’s position, which is player.x, player.y. Save the file and view it. View the file using the inspect element option, and you should see something like figure 2.   Figure 2: Controlling the hero You can now control the movement of the hero in the game. Summary In this two-part series, you learned about working with Crafty.js. Specifically, you learned how to work with the Crafty API, create entities, work with sprites, create components, and control entities via mouse/touch. About the author Robi Sen, CSO at Department 13, is an experienced inventor, serial entrepreneur, and futurist whose dynamic twenty-plus-year career in technology, engineering, and research has led him to work on cutting edge projects for DARPA, TSWG, SOCOM, RRTO, NASA, DOE, and the DOD. Robi also has extensive experience in the commercial space, including the co-creation of several successful start-up companies. He has worked with companies such as UnderArmour, Sony, CISCO, IBM, and many others to help build new products and services. Robi specializes in bringing his unique vision and thought process to difficult and complex problems, allowing companies and organizations to find innovative solutions that they can rapidly operationalize or go to market with.
Read more
  • 0
  • 0
  • 3801
Unlock access to the largest independent learning library in Tech for FREE!
Get unlimited access to 7500+ expert-authored eBooks and video courses covering every tech area you can think of.
Renews at $19.99/month. Cancel anytime
article-image-tabula-rasa-nurturing-your-site-tablets
Packt
09 Mar 2012
16 min read
Save for later

Tabula Rasa: Nurturing your Site for Tablets

Packt
09 Mar 2012
16 min read
The human touch There's a reason touchscreen interfaces were rarely used before Apple re-invented them in the iPhone. It's because programming them is very difficult. With a mouse-driven interface you have a single point of contact: the mouse's pointer. With a touchscreen, you potentially have ten points of contact, each one with a separate motion. And you also have to deal with limiting spurious input when the user accidentally touches the tablet when they didn't mean to. Does the user's swipe downward mean they want to scroll the page or to drag a single page element? The questions go on to infinity. With this article, we stand on the shoulders of those giants who have done the heavy lifting and given us a JavaScript interface that registers touch and gestures for use in our web pages. Many Bothans died to bring us this information. To understand the tablet is to understand the touch interface, and in order to understand the touch interface, we need to learn how touch events differ from mouse events. But that begs the question: what is an event? The event-driven model Many developers use JavaScript-based events and have not even the slightest clue as to what they can do or their power. In addition, many developers get into situations where they don't know why their events are misfiring or, worse yet, bubbling to other event handlers and causing a cascade of event activity. As you may or may not know, an HTML document is made up of a series of tags organized in a hierarchical structure called the HTML document. In JavaScript, this document is referred to through the reserved word document. Simple enough, right? Well, what if I want to interact with the tag inside of a document, and not the document as a whole? Well, for that we need a way of addressing nested items inside the main <html> tag. For that, we use the Document Object Model (DOM). DOM is a cross-platform and language-independent convention for representing and interacting with objects in HTML, XHTML, and XML documents. Aspects of the DOM (such as its elements) may be addressed and manipulated within the syntax of the programming language in use. The public interface of a DOM is specified in its Application Programming Interface (API). For more details on DOM, refer to the Wikipedia document at: http://en.wikipedia.org/wiki/Document_Object_Model. The body of that document then becomes document.body. The head of the document, likewise, becomes document.head. Now, what happens when your mouse interacts with this web page? This is said to be a DOM event. When you click, the elements that are the receivers of that action are said to propagate the event through the DOM. In the early days, Microsoft and Netscape/Firefox had competing ways of handling those events. But they finally gave way to the modern W3C's standard, which unifies the two ways and, even more importantly, jQuery has done a lot to standardize the way we think about events and event handling. In most browsers today, mouse events are pretty standardized, as we are now more than 20 years into the mouse-enabled computing era: For tablets and touchscreen phones, obviously, there is no mouse. There are only your fingers to serve the purpose of the mouse. And here's where things get simultaneously complicated as well as simple. Touch and go Much of what we talk about as touch interaction is made up of two distinct types of touches—single touches and gestures. A single touch is exactly that. One finger placed on the screen from the start till the end. A gesture is defined as one or more fingers touching the surface of the area and accompanied by a specific motion: Touch + Motion. To open most tablets, you swipe your finger across a specific area. To scroll inside a div element, you use two fingers pushing up and down. In fact, scrolling itself is a gesture and tablets only respond to the scroll event once it's over. We will cover more on that later. Gestures have redefined user interaction. I wonder how long it took for someone to figure out that the zoom in and zoom out is best accomplished with a pinch of the fingers? It seems so obvious once you do it and it immediately becomes second nature. My mom was pinching to zoom on her iPhone within the first 5 minutes of owning it. Touch events are very similar to multiple mouse events without a hover state. There is no response from the device when a finger is over the device but has not pressed down. There is an effort on the part of many mobile OS makers to simulate the hover event by allowing the hover event to trigger with the first click, and the click event to trigger with the second click on the same object. I would advise against using it for any meaningful user interaction as it is inconsistently implemented, and many times the single click triggers the link as well as the hover-reveal in drop-down menus. Not using the hover event to guide users through navigation changes the way we interact with a web page. Much of the work we've done to guide users through our pages is based on the hover-response event model to clue users in on where links are. We have to get beyond that. Drop-down menus quickly become frustrating at the second and third levels, especially if the click and hover events were incorrectly implemented in the desktop browser. Forward and back buttons are rendered obsolete by a forward and backwards swipe gesture. The main event There are basically three touch events—touchstart, touchmove, and touchend. Gesture events are, likewise: gesturestart, gesturemove, and gestureend. All gestures register a touch event but not all touch events register gestures. Gestures are registered when multiple fingers make contact with the touch surface and register significant location change in a concerted effort, such as two or more fingers swiping, a pinch action, and so on. In general, I've found it a good practice to use touch events to register finger actions; but it is required to return null on a touch event when there are multiple fingers involved and to handle such events with gestures. jQuery mobile has a nice suite of touch events built into its core that we can hook into. But jQuery and jQuery mobile sometimes fall short of the interaction we want to have for our users, so we'll outline best practices for adding customized user touch events to both the full and mobile version of the demo site. Let's get started… Time for action – adding a swipe advance to the home page The JavaScript to handle touch events is a little tricky; so, pay attention: Add the following lines to both sites/all/themes/dpk/js/global.js and sites/all/themes/dpk_mobile/js/global.js: Drupal.settings.isTouchDevice = function() { return "ontouchstart" in window; } if (Drupal.settings.isTouchDevice() ) { Drupal.behaviors.jQueryMobileSlideShowTouchAdvance = { attach: function(context, settings) { self = Drupal.behaviors.jQueryMobileSlideShowTouchAdvance; jQuery.each(jQuery(".views_slideshow_cycle_main. viewsSlideshowCycle-processed"), function(idx, value) { value.addEventListener("touchstart", self. handleTouchStart); jQuery(value).addClass("views-slideshow-mobileprocessed"); }) jQuery(self).bind("swipe", self.handleSwipe); }, detach: function() { }, original: { x: 0, y: 0}, changed: { x: 0, y: 0}, direction: { x: "", y: "" }, fired: false,handleTouchStart: function(evt) { self = Drupal.behaviors.jQueryMobileSlideShowTouchAdvance; if (evt.touches) { if (evt.targetTouches.length != 1) { return false; } if (evt.touches.length) { evt.preventDefault(); evt. stopPropagation() } self.original = { x: evt.touches[0].clientX, y: evt. touches[0].clientY } self.target = jQuery(this).attr("id").replace("views_ slideshow_cycle_main_", ""); Drupal.viewsSlideshow.action({ "action": "pause", "slideshowID": self.target }); evt.target.addEventListener("touchmove", self. handleTouchMove); evt.target.addEventListener("touchend", self. handleTouchEnd); } }, handleTouchMove: function(evt) { self = Drupal.behaviors.jQueryMobileSlideShowTouchAdvance; self.changed = { x: (evt.touches.length) ? evt.touches[0].clientX: evt.changedTouches[0].clientX, y: (evt.touches.length) ? evt.touches[0].clientY: evt.changedTouches[0].clientY }; h = parseInt(self.original.x - self.changed.x), v = parseInt(self.original.y - self.changed.y); if (h !== 0) { self.direction.x = (h < 0) ? "right":"left"; } if (v !== 0) { self.direction.y = (v < 0) ? "up": "down"; } jQuery(self).trigger("swipe"); }, handleTouchEnd: function(evt) { self = Drupal.behaviors.jQueryMobileSlideShowTouchAdvance; evt.target.removeEventListener("touchmove", self. handleTouchMove); evt.target.removeEventListener("touchend", self. handleTouchEnd); self.fired = false; }, handleSwipe: function(evt) { self = Drupal.behaviors.jQueryMobileSlideShowTouchAdvance; if (evt != undefined && self.fired == false) { Drupal.viewsSlideshow.action({ "action": (self.direction.x == "left")?"nextSlide":"previousSlide", "slideshowID": self.target}); self.fired = true; //only fire advance once per touch } } } } Clear Drupal's cache by either navigating to Configuration | Performance and clicking on the Clear cache button or entering these lines in a terminal: cd ~/sites/dpk/drush cc all Navigate to either home page with a touch-enabled device and you should be able to advance the home page slideshow with your fingers. What just happened? Let's take a look at how this code works. First, we have a function, isTouchDevice. This function returns true/false values if touch events are enabled on the browser. We use an if statement to wall off the touchscreen code, so browsers that aren't capable don't register an error. The Drupal behavior jQueryMobileSlideShowTouchAdvance has the attach and detach functions to satisfy the Drupal behavior API. In each function, we locally assign the self variable with the value of the entire object. We'll use this in place of the this keyword. In the Drupal behavior object, this can sometimes ambiguously refer to the entire object, or to the current sub-object. In this case, we want the reference to be to just the sub-object so we assign it to self. The attach function grabs all slideshow_cycle div elements in a jQuery each loop. The iteration of the loop adds an event listener to the div tag. It's important to note that the event listener is not bound with jQuery event binding. jQuery event binding does not yet support touch events. There's an effort to add them, but they are not in the general release that is used with Drupal 7. We must then add them with the browser native function, AddEventListener. We use the handleTouchStart method to respond to the touchstart event. We will add touchend and touchmove events after the touchstart is triggered.The other event that we're adding listens to this object for the swipe event. This is a custom event we will create that will be triggered when a swipe action happens. We will cover more on that shortly.The detach function is used to add cleanup to items when they are removed from the DOM. Currently, we have no interaction that removes items from the DOM and therefore no cleanup that's necessary for that removal to take place.Next, we add some defaults—original, changed, direction, and fired. We'll use those properties in our event response methods.HandleTouchStart event is fired when the finger first touches the surface. We make sure the evt.touches object has value and is only one touch. We want to disregard touches that are gestures. Also, we use preventDefault and stopPropagation on the event to keep it from bubbling up to other items in the DOM. self.original is the variable that will hold the touch's original coordinates. We store the values for touch[0]. We also name the target by getting the DOM ID of the cycle containing the div element. We can use string transforms on that ID to obtain the ID of the jQuery cycle being touched and will use that value when we send messages to the slideshow, based on the touch actions, like we do in the next line. We tell the slideshow to pause normal activity while we figure out what the user wants. To figure that out, we add touchmove and touchend events listening to the div element. handleTouchMove figures out the changed touch value. It does so by looking at the ClientX and ClientY values in the touch event.Some browsers support the changedTouches value which will do some calculations on how much the touch has changed since the last event was triggered. If it's available, we use it, or we use the value of the X and Y coordinates in the touch event's touches array. We do some subtraction against the original touch to find out how much the touch has changed and in what direction. We use self.direction to store the direction of the change. We store the direction in and tell the world that a swipe has begun on our div element by triggering a custom event on our self object.If you remember correctly, we used the handleSwipe method to respond to the swipe event. In handleSwipe we make sure the event has not already fired. If it hasn't, we use that swipe event to trigger a next or previous action on our jQuery cycle slideshow. Once we've fired the event, we change the self.fired to true so it will only fire once per touch. In the touchend responder, HandleTouchEnd, we remove both the touchmove and touchend responders and reset the fired state.But adding the touch events to both the desktop and the mobile themes begs the question, "Into which category does the table fall?" Have a go hero – adding a swipe gesture Add a swipe gesture event to the Menu Item page that allows you to scroll through menu items. The changing landscape (or portrait) Responsive web design is a design discipline that believes that the same markup should be used for both desktop and mobile screens, with the browser managing the display of items, rather than the user choosing an experience. If the screen is smaller, the layout adjusts and content emphasis remains.Conversely, the popularity of Internet-connected game consoles and DVI ports on large screen televisions gives us yet another paradigm for web pages—the large screen. I sit in front of a 72" TV screen and connect it to either my laptop or iPad and I have a browsing experience that is more passive, but completely immersive.Right now, I bet you're thinking, "So which is it Mr Author, two sites or one?" Well, both, actually. In some cases, with some interactions it will be necessary to do two site themes and maintain them both. In some cases, when you can start from scratch, you can do a design that can work on every browser screen size. Let's start over and put responsive design principals to work with what we already know about media queries and touch interfaces. "Starting over" or "Everything you know about designing websites is wrong" Responsive web design forces the designer to start over—to forget the artificial limitations of the size that print imposes and to start with a blank canvas. Once that blank canvas is in place, though, how do you fill it? How do you create "The One True Design" (cue the theme music)?This book is not a treatise on how to create the perfect design. For that, I can recommend A Book Apart and anything published by smashingmagazine.com. Currently, they are at the forefront of this movement and regularly publish ideas and information that is helpful without too much technical jargon.No, this book is more about giving you strategies to implement the designs you're given or that you create using Drupal. In point of fact, responsive design, at the time of writing, is in its infancy and will change significantly over the next 10 years, as new technology forces us to rethink our assumptions about what books, television, and movies are and what the Web is.So suffice to say, it begins with content. Prioritizing content is the job of the designer. Items you want the user to perceive first, second, and third are the organizing structure of your responsive design makeover. In most instances, it's helpful to present the web developer with four views of the website. Wire framing made easy Start with wireframes. A great wire framing tool is called Balsamiq. It has a purposefully "rough" look to all of the elements you use. That way, it makes you focus on the elements and leave the design for a later stage. It's also helpful for focusing clients on the elements. Many times the stake holders see a mockup and immediately begin the discussion of "I like blue but I don't like green/I like this font, but don't like that one." It can be difficult to move the stake holders out of this mindset, but presenting them with black-and-white chalk-style drawings of website elements can, in many cases, be helpful. Balsamiq is a great tool for doing just that: These were created with Balsamiq but could have been created in almost any primitive drawing program. There are many free ones as well as the more specialized pay ones. A simple layout like this is very easy to plan and implement. But very few of the websites you develop will ever be this simple. Let's take for instance that the menu item we have not, as yet, implemented, is for online ordering. How does that work? What do those screens look like? At this point we have a Menu page but, as per this mockup, that menu page will become the online ordering section. How do we move these menu items we created to a place where they can be put in an order and paid for? And more importantly, how does each location know what was ordered from their location?These are questions that come up in the mockup and requirements phase and whether you are building the site yourself or being given requirements from a superior, or a client, you now have a better idea of the challenges you will face implementing the single design for this site. With that, we've been given these mockups for the new online ordering system. The following mockup diagram is for adding an order: The following mockup diagram is for placing an order: We'll implement these mockups using the Drupal 7 Commerce module. The Commerce module is just a series of customized data entities and views that we can use as the building blocks of our commerce portion. We'll theme the views in the standard Drupal way but with an eye to multi-width screens, lack of hover state, and keeping in mind "hit zones" with fingers on small mobile devices. We'll also add some location awareness to assist with the delivery process. Once an order is placed, an e-mail will need to be sent to the correct franchise notifying them of the pizza order and initiating the process of getting it out the door.
Read more
  • 0
  • 0
  • 3736

article-image-cloud-enabling-your-apps
Packt
08 May 2013
7 min read
Save for later

Cloud-enabling Your Apps

Packt
08 May 2013
7 min read
(For more resources related to this topic, see here.) Which cloud services can you use with Titanium? Here is a comparison of the services offered by three cloud-based providers who have been proven to work with Titanium: Appcelerator Cloud Services Parse StackMob Customizable storage Yes Yes Yes Push notifications Yes Yes Yes E-mail Yes No No Photos Yes Yes Yes Link with Facebook/Twitter account Yes Yes Yes User accounts Yes Yes Yes The services offered by these three leading contenders are very similar. The main difference is the cost. Which is the best one for you? It depends on your requirements; you will have to do the cost/benefit analysis to work out the best solution for you. Do you need more functionality than this? No problem, look around for other PaaS providers. The PaaS service offered by RedHat has been proven to integrate with Titanium and offers far more flexibility. There is an example of a Titanium app developed with RedHat Openshift at https://openshift.redhat.com/community/blogs/developing-mobile-appsfor-the-cloud-with-titanium-studio-and-the-openshift-paas It doesn't stop there; new providers are coming along almost every month with new and grand ideas for web and mobile integration. My advice would be to take the long view. Draw up a list of what you require initially for your app and what you realistically want in the next year. Check this list against the cloud providers. Can they satisfy all your needs at a workable cost? They should do; they should be flexible enough to cover your plans. You should not need to split your solution between providers. Clouds are everywhere Cloud-based services offer more than just storage. Appcelerator Cloud Services Appcelerator Cloud Services ( ACS) is well integrated into Titanium. The API includes commands for controlling ACS cloud objects. In the first example in this article we are going to add commentary functionality to the simple forex app. Forex commentary is an ideal example of the benefits of cloud-based storage where your data is available across all devices. First, let's cover some foreground to the requirements. First, let's cover some foreground to the requirements. The currency markets are open 24 hours a day, 5 days a week and trading opportunities can present themselves at any point. You will not be in front of your computer all of the time so you will need to be able to access and add commentary when you are on your phone or at home on your PC. This is where the power of the cloud really starts to hit home. We already know that you can create apps for a variety of devices using Appcelerator. This is good; we can access our app from most phones, but now using the cloud we can also access our commentary from anywhere. So, comments written on the train about the EURUSD rate can be seen later when at home looking at the PC. When we are creating forex commentary, we will store the following: The currency pair (that is EURUSD) ‹ The rate (the current exchange rate) The commentary (what we think about the exchange rate) We will also store the date and time of the commentary. This is done automatically by ACS. All objects include the date they were created. ACS allows you to store key value pairs (which is the same as Ti.App.Properties), that is AllowUserToSendEmails: True, or custom objects. We have several attributes to our commentary post so a key value pair will not suffice. Instead we will be using a custom object. We are going to add a screen that will be called when a user selects a currency. From this screen a user can enter commentary on the currency. Time for action – creating ACS custom objects Perform the following steps to create ACS custom objects: Enable ACS in your existing app. Go to tiapp.xml and click on the Enable... button on the Cloud Services section. Your project will gain a new Ti.Cloud module and the ACS authentication keys will be shown: Go to the cloud website, https://my.appcelerator.com/apps, find your app, and select Manage ACS. Select Development from the selection buttons at the top. You need to define a user so your app can log in to ACS. From the App Management tab select Users from the list on the right. If you have not already created a suitable user, do it now. We will split the functionality in this article over two files. The first file will be called forexCommentary.js and will contain the cloud functionality, and the second file called forexCommentaryView.js will contain the layout code. Create the two new files. Before we can do anything with ACS, we need to log in. Create an init function in forexCommentary.js which will log in the forex user created previously: function init(_args) { if (!Cloud.sessionId) { Cloud.Users.login({ login: 'forex', password: 'forex' }, function (e) { if (e.success) { _args.success({user : e.users[0]}); } else { _args.error({error: e.error}); } }); } This is not a secure login, it's not important for this example. If you need greater security, use the Ti.Cloud.Users. secureLogin functionality. Create another function to create a new commentary object on ACS. The function will accept a parameter containing the attribute's pair, rate, and commentary and create a new custom object from these. The first highlighted section shows how easy it is to define a custom object. The second highlighted section shows the custom object being passed to the success callback when the storage request completes: function addCommentary(_args) { // create a new currency commentary Cloud.Objects.create({ classname: className, fields: { pair: _args.pair, rate: _args.rate, comment: _args.commentary } }, function (e) { if (e.success) { _args.success(e.forexCommentary[0]); } else { _args.error({error: e.error}); } }); } Now to the layout. This will be a simple form with a text area where the commentary can be added. The exchange rate and currency pair will be provided from the app's front screen. Create a TextArea object and add it to the window. Note keyboardType of Ti.UI.KEYBOARD_ASCII which will force a full ASCII layout keyboard to be displayed and returnKeyType of Ti.UI.RETURNKEY_DONE which will add a done key used in the next step: var commentary = Ti.UI.createTextArea({ borderWidth:2, borderColour:'blue', borderRadius:5, keyboardType: Ti.UI.KEYBOARD_ASCII, returnKeyType: Ti.UI.RETURNKEY_DONE, textAlign: 'left', hintText: 'Enter your thoughts on '+thePair, width: '90%', height : 150 }); mainVw.add(commentary); Now add an event listener which will listen for the done key being pressed and when triggered will call the function to store the commentary with ACS: commentary.addEventListener('return', function(e) {forex.addCommentary({ pair: thePair, rate: theRate, commentary: e.value}) }); Finally add the call to log in the ACS user when the window is first opened: var forex = require('forexCommentary'); forex.init(); Run the app and enter some commentary. What just happened? You created functions to send a custom defined object to the server. Commentary entered on the phone is almost immediately available for viewing on the Appcelerator console (https://my.appcelerator.com/apps) and therefore available to be viewed by all other devices and formats. Uploading pictures Suppose you want to upload a picture, or a screenshot? This next example will show how easy it is to upload a picture to ACS.
Read more
  • 0
  • 0
  • 3695

article-image-creating-city-information-app-customized-table-views
Packt
08 Oct 2015
19 min read
Save for later

Creating a City Information App with Customized Table Views

Packt
08 Oct 2015
19 min read
In this article by Cecil Costa, the author of Swift 2 Blueprints, we will cover the following: Project overview Setting it up The first scene Displaying cities information (For more resources related to this topic, see here.) Project overview The idea of this app is to give users information about cities such as the current weather, pictures, history, and cities that are around. How can we do it? Firstly, we have to decide on how the app is going to suggest a city to the user. Of course, the most logical city would be the city where the user is located, which means that we have to use the Core Location framework to retrieve the device's coordinates with the help of GPS. Once we have retrieved the user's location, we can search for cities next to it. To do this, we are going to use a service from http://www.geonames.org/. Other information that will be necessary is the weather. Of course, there are a lot of websites that can give us information on the weather forecast, but not all of them offer an API to use it for your app. In this case, we are going to use the Open Weather Map service. What about pictures? For pictures, we can use the famous Flickr. Easy, isn't it? Now that we have the necessary information, let's start with our app. Setting it up Before we start coding, we are going to register the needed services and create an empty app. First, let's create a user at geonames. Just go to http://www.geonames.org/login with your favorite browser, sign up as a new user, and confirm it when you receive a confirmation e-mail. It may look like everything has been done, however, you still need to upgrade your account to use the API services. Don't worry, it's free! So, open http://www.geonames.org/manageaccount and upgrade your account. Don't use the user demo provided by geonames, even for development. This user exceeds its daily quota very frequently. With geonames, we can receive information on cities by their coordinates, but we don't have the weather forecast and pictures. For weather forecasts, open http://openweathermap.org/register and register a new user and API. Lastly, we need a service for the cities' pictures. In this case, we are going to use Flickr. Just create a Yahoo! account and create an API key at https://www.flickr.com/services/apps/create/. While creating a new app, try to investigate the services available for it and their current status. Unfortunately, the APIs change a lot like their prices, their terms, and even their features. Now, we can start creating the app. Open Xcode, create a new single view application for iOS, and call it Chapter 2 City Info. Make sure that Swift is the main language like the following picture: The first task here is to add a library to help us work with JSON messages. In this case, a library called SwiftyJSON will solve our problem. Otherwise, it would be hard work to navigate through the NSJSONSerialization results. Download the SwiftyJSON library from https://github.com/SwiftyJSON/SwiftyJSON/archive/master.zip, then uncompress it, and copy the SwiftyJSON.swift file in your project. Another very common way of installing third party libraries or frameworks would be to use CocoaPods, which is commonly known as just PODs. This is a dependency manager, which downloads the desired frameworks with their dependencies and updates them. Check https://cocoapods.org/ for more information. Ok, so now it is time to start coding. We will create some functions and classes that should be common for the whole program. As you know, many functions return NSError if something goes wrong. However, sometimes, there are errors that are detected by the code, like when you receive a JSON message with an unexpected struct. For this reason, we are going to create a class that creates custom NSError. Once we have it, we will add a new file to the project (command + N) called ErrorFactory.swift and add the following code: import Foundation class ErrorFactory {{ static let Domain = "CityInfo" enum Code:Int { case WrongHttpCode = 100, MissingParams = 101, AuthDenied = 102, WrongInput = 103 } class func error(code:Code) -> NSError{ let description:String let reason:String let recovery:String switch code { case .WrongHttpCode: description = NSLocalizedString("Server replied wrong code (not 200, 201 or 304)", comment: "") reason = NSLocalizedString("Wrong server or wrong api", comment: "") recovery = NSLocalizedString("Check if the server is is right one", comment: "") case .MissingParams: description = NSLocalizedString("There are some missing params", comment: "") reason = NSLocalizedString("Wrong endpoint or API version", comment: "") recovery = NSLocalizedString("Check the url and the server version", comment: "") case .AuthDenied: description = NSLocalizedString("Authorization denied", comment: "") reason = NSLocalizedString("User must accept the authorization for using its feature", comment: "") recovery = NSLocalizedString("Open user auth panel.", comment: "") case .WrongInput: description = NSLocalizedString("A parameter was wrong", comment: "") reason = NSLocalizedString("Probably a cast wasn't correct", comment: "") recovery = NSLocalizedString("Check the input parameters.", comment: "") } return NSError(domain: ErrorFactory.Domain, code: code.rawValue, userInfo: [ NSLocalizedDescriptionKey: description, NSLocalizedFailureReasonErrorKey: reason, NSLocalizedRecoverySuggestionErrorKey: recovery ]) } } The previous code shows the usage of NSError that requires a domain, which is a string that differentiates the error type/origin and avoids collisions in the error code. The error code is just an integer that represents the error that occurred. We used an enumeration based on integer values, which makes it easier for the developer to remember and allows us to convert its enumeration to an integer easily with the rawValue property. The third argument of an NSError initializer is a dictionary that contains messages, which can be useful to the user (actually to the developer). Here, we have three keys: NSLocalizedDescriptionKey: This contains a basic description of the error NSLocalizedFailureReasonErrorKey: This explains what caused the error NSLocalizedRecoverySuggestionErrorKey: This shows what is possible to avoid this error As you might have noticed, for these strings, we used a function called NSLocalizedString, which will retrieve the message in the corresponding language if it is set to the Localizable.strings file. So, let's add a new file to our app and call it Helpers.swift; click on it for editing. URLs have special character combinations that represent special characters, for example, a whitespace in a URL is sent as a combination of %20 and a open parenthesis is sent with the combination of %28. The stringByAddingPercentEncodingWithAllowedCharacters string method allows us to do this character conversion. If you need more information on the percent encoding, you can check the Wikipedia entry at https://en.wikipedia.org/wiki/Percent-encoding. As we are going to work with web APIs, we will need to encode some texts before we send them to the corresponding server. Type the following function to convert a dictionary into a string with the URL encoding: func toUriEncoded(params: [String:String]) -> String { var records = [String]() for (key, value) in params { let valueEncoded = value.stringByAddingPercentEncodingWithAllowedCharacters(.URLHostAllowedCharacterSet()) records.append("(key)=(valueEncoded!)") } return "&".join(records) } Another common task is to call the main queue. You might have already used a code like dispatch_async(dispatch_get_main_queue(), {() -> () in … }), however, it is too long. We can reduce it by calling it something like M{…}. So, here is the function for it: func M(((completion: () -> () ) { dispatch_async(dispatch_get_main_queue(), completion) } A common task is to request for JSON messages. To do so, we just need to know the endpoint, the required parameters, and the callback. So, we can start with this function as follows: func requestJSON(urlString:String, params:[String:String] = [:], completion:(JSON, NSError?) -> Void){ let fullUrlString = "(urlString)?(toUriEncoded(params))" if let url = NSURL(string: fullUrlString) { NSURLSession.sharedSession().dataTaskWithURL(url) { (data, response, error) -> Void in if error != nil { completion(JSON(NSNull()), error) return } var jsonData = data! var jsonString = NSString(data: jsonData, encoding: NSUTF8StringEncoding)! Here, we have to add a tricky code, because the Flickr API is always returned with a callback function called jsonFlickrApi while wrapping the corresponding JSON. This callback must be removed before the JSON text is parsed. So, we can fix this issue by adding the following code: // if it is the Flickr response we have to remove the callback function jsonFlickrApi() // from the JSON string if (jsonString as String).characters.startsWith("jsonFlickrApi(".characters) { jsonString = jsonString.substringFromIndex("jsonFlickrApi(".characters.count) let end = (jsonString as String).characters.count - 1 jsonString = jsonString.substringToIndex(end) jsonData = jsonString.dataUsingEncoding(NSUTF8StringEncoding)! } Now, we can complete this function by creating a JSON object and calling the callback: let json = JSON(data:jsonData) completion(json, nil) }.resume() }else { completion(JSON(NSNull()), ErrorFactory.error(.WrongInput)) } } At this point, the app has a good skeleton. It means that, from now on, we can code the app itself. The first scene Create a project group (command + option + N) for the view controllers and move the ViewController.swift file (created by Xcode) to this group. As we are going to have more than one view controller, it is also a good idea to rename it to InitialViewController.swift: Now, open this file and rename its class from ViewController to InitialViewController: class InitialViewController: UIViewController { Once the class is renamed, we need to update the corresponding view controller in the storyboard by: Clicking on the storyboard. Selecting the view controller (the only one we have till now). Going to the Identity inspector by using the command+ option + 3 combination. Here, you can update the class name to the new one. Pressing enter and confirming that the module name is automatically updated from None to the product name. The following picture demonstrates where you should do this change and how it should be after the change: Great! Now, we can draw the scene. Firstly, let's change the view background color. To do it, select the view that hangs from the view controller. Go to the Attribute Inspector by pressing command+ option + 4, look for background color, and choose other, as shown in the following picture: When the color dialog appears, choose the Color Sliders option at the top and select the RGB Sliders combo box option. Then, you can change the color as per your choice. In this case, let's set it to 250 for the three colors: Before you start a new app, create a mockup of every scene. In this mockup, try to write down the color numbers for the backgrounds, fonts, and so on. Remember that Xcode still doesn't have a way to work with styles as websites do with CSS, meaning that if you have to change the default background color, for example, you will have to repeat it everywhere. On the storyboard's right-hand side, you have the Object Library, which can be easily accessed with the command + option + control + 3 combination. From there, you can search for views, view controllers, and gestures, and drag them to the storyboard or scene. The following picture shows a sample of it: Now, add two labels, a search bar, and a table view. The first label should be the app title, so let's write City Info on it. Change its alignment to center, the font to American Typewriter, and the font size to 24. On the other label, let's do the same, but write Please select your city and its font size should be 18. The scene must result in something similar to the following picture: Do we still need to do anything else on this storyboard scene? The answer is yes. Now it is time for the auto layout, otherwise the scene components will be misplaced when you start the app. There are different ways to add auto layout constraints to a component. An easy way of doing it is by selecting the component by clicking on it like the top label. With the control key pressed, drag it to the other component on which the constraint will be based like the main view. The following picture shows a sample of a constraint being created from a table to the main view: Another way is by selecting the component and clicking on the left or on the middle button, which are to the bottom-right of the interface builder screen. The following picture highlights these buttons: Whatever is your favorite way of adding constraints, you will need the following constraints and values for the current scene: City Info label Center X equals to the center of superview (main view), value 0 City Info label top equals to the top layout guide, value 0 Select your city label top vertical spacing of 8 to the City Info label Select your city label alignment center X to superview, value 0 Search bar top value 8 to select your city label Search bar trailing and leading space 0 to superview Table view top space (space 0) to the search bar Table view trailing and leading space 0 to the search bar Table view bottom 0 to superview Before continuing, it is a good idea to check whether the layout suits for every resolution. To do it, open the assistant editor with command + option + .return and change its view to Preview: Here, you can have a preview of your screen on the device. You can also rotate the screens by clicking on the icon with a square and a arched arrow over it: Click on the plus sign to the bottom-left of the assistant editor to add more screens: Once you are happy with your layout, you can move on to the next step. Although the storyboard is not yet done, we are going to leave it for a while. Click on the InitialViewController.swift file. Let's start receiving information on where the device is using the GPS. To do it, import the Core Location framework and set the view controller as a delegate: import CoreLocation class InitialViewController: UIViewController, CLLocationManagerDelegate { After this, we can set the core location manager as a property and initialize it on viewDidLoadMethod. Type the following code to set locationManager and initialize InitialViewController: var locationManager = CLLocationManager() override func viewDidLoad() { super.viewDidLoad() locationManager.delegate = self locationManager.desiredAccuracy = kCLLocationAccuracyThreeKilometers locationManager.distanceFilter = 3000 if locationManager.respondsToSelector(Selector("requestWhenInUseAuthorization")) { locationManager.requestWhenInUseAuthorization() } locationManager.startUpdatingLocation() } After initializing the location manager, we have to check whether the GPS is working or not by implementing the didUpdateLocations method. Right now, we are going to print the last location and nothing more: func locationManager(manager: CLLocationManager!, didUpdateLocations locations: [CLLocation]!){ let lastLocation = locations.last! print(lastLocation) } Now, we can test the app. However, we still need to perform one more step. Go to your Info.plist file by pressing command + option + J and the file name. Add a new entry with the NSLocationWhenInUseUsageDescription key and change its type to String and its value to This app needs to know your location. This last step is mandatory since iOS 8. Press play and check whether you have received a coordinate, but not very frequently. Displaying cities information The next step is to create a class to store the information received from the Internet. In this case, we can do it in a straightforward manner by copying the JSON object properties in our class properties. Create a new group called Models and, inside it, a file called CityInfo.swift. There you can code CityInfo as follows: class CityInfo { var fcodeName:String? var wikipedia:String? var geonameId: Int! var population:Int? var countrycode:String? var fclName:String? var lat : Double! var lng: Double! var fcode: String? var toponymName:String? var name:String! var fcl:String? init?(json:JSON){){){ // if any required field is missing we must not create the object. if let name = json["name"].string,,, geonameId = json["geonameId"].int, lat = json["lat"].double, lng = json["lng"].double { self.name = name self.geonameId = geonameId self.lat = lat self.lng = lng }else{ return nil } self.fcodeName = json["fcodeName"].string self.wikipedia = json["wikipedia"].string self.population = json["population"].int self.countrycode = json["countrycode"].string self.fclName = json["fclName"].string self.fcode = json["fcode"].string self.toponymName = json["toponymName"].string self.fcl = json["fcl"].string } } Pay attention that our initializer has a question mark on its header; this is called a failable initializer. Traditional initializers always return a new instance of the newly requested object. However, with failable initializers, you can return a new instance or a nil value, indicating that the object couldn't be constructed. In this initializer, we used an object of the JSON type, which is a class that belongs to the SwiftyJSON library/framework. You can easily access its members by using brackets with string indices to access the members of a json object, like json ["field name"], or using brackets with integer indices to access elements of a json array. Doesn't matter, the way you have to use the return type, it will always be a JSON object, which can't be directly assigned to the variables of another built-in types, such as integers, strings, and so on. Casting from a JSON object to a basic type can be done by accessing properties with the same name as the destination type, such as .string for casting to string objects, .int for casting to int objects, .array or an array of JSON objects, and so on. Now, we have to think about how this information is going to be displayed. As we have to display this information repeatedly, a good way to do so would be with a table view. Therefore, we will create a custom table view cell for it. Go to your project navigator, create a new group called Cells, and add a new file called CityInfoCell.swift. Here, we are going to implement a class that inherits from UITableViewCell. Note that the whole object can be configured just by setting the cityInfo property: import UIKit class CityInfoCell:UITableViewCell { @IBOutlet var nameLabel:UILabel! @IBOutlet var coordinates:UILabel! @IBOutlet var population:UILabel! @IBOutlet var infoImage:UIImageView! private var _cityInfo:CityInfo! var cityInfo:CityInfo { get { return _cityInfo } set (cityInfo){ self._cityInfo = cityInfo self.nameLabel.text = cityInfo.name if let population = cityInfo.population { self.population.text = "Pop: (population)" }else { self.population.text = "" } self.coordinates.text = String(format: "%.02f, %.02f", cityInfo.lat, cityInfo.lng) if let _ = cityInfo.wikipedia { self.infoImage.image = UIImage(named: "info") } } } } Return to the storyboard and add a table view cell from the object library to the table view by dragging it. Click on this table view cell and add three labels and one image view to it. Try to organize it with something similar to the following picture: Change the labels font family to American Typewriter, and the font size to 16 for the city name and 12 for the population and the location label..Drag the info.png and noinfo.png images to your Images.xcassets project. Go back to your storyboard and set the image to noinfo in the UIImageView attribute inspector, as shown in the following screenshot: As you know, we have to set the auto layout constraints. Just remember that the constraints will take the table view cell as superview. So, here you have the constraints that need to be set: City name label leading equals 0 to the leading margin (left) City name label top equals 0 to the super view top margin City name label bottom equals 0 to the super view bottom margin City label horizontal space 8 to the population label Population leading equals 0 to the superview center X Population top equals to -8 to the superview top Population trailing (right) equals 8 to the noinfo image Population bottom equals 0 to the location top Population leading equals 0 to the location leading Location height equals to 21 Location trailing equals 8 to the image leading Location bottom equals 0 to the image bottom Image trailing equals 0 to the superview trailing margin Image aspect ratio width equals 0 to the image height Image bottom equals -8 to the superview bottom Image top equals -8 to the superview top Has everything been done for this table view cell? Of course not. We still need to set its class and connect each component. Select the table view cell and change its class to CityInfoCell: As we are here, let's do a similar task that is to change the cell identifier to cityinfocell. This way, we can easily instantiate the cell from our code: Now, you can connect the cell components with the ones we have in the CityInfoCell class and also connect the table view with the view controller: @IBOutlet var tableView: UITableView!! There are different ways to connect a view with the corresponding property. An easy way is to open the assistant view with the command + option + enter combination, leaving the storyboard on the left-hand side and the Swift file on the right-hand side. Then, you just need to drag the circle that will appear on the left-hand side of the @IBOutlet or the @IBAction attribute and connect with the corresponding visual object on the storyboard. After this, we need to set the table view delegate and data source, and also the search bar delegate with the view controller. It means that the InitialViewController class needs to have the following header. Replace the current InitialViewController header with: class InitialViewController: UIViewController, CLLocationManagerDelegate, UITableViewDataSource, UITableViewDelegate, UISearchBarDelegate { Connect the table view and search bar delegate and the data source with the view controller by control dragging from the table view to the view controller's icon at the top of the screen, as shown in the following screenshot: Summary In this article, you learned how to create custom NSError, which is the traditional way of reporting that something went wrong. Every time a function returns NSError, you should try to solve the problem or report what has happened to the user. We could also appreciate the new way of trapping errors with try and catch a few times. This is a new feature on Swift 2, but it doesn't mean that it will replace NSError. They will be used in different situations. Resources for Article: Further resources on this subject: Nodes[article] Network Development with Swift[article] Playing with Swift [article]
Read more
  • 0
  • 0
  • 3573

article-image-introducing-rubymotion-and-hello-world-app
Packt
22 Jul 2013
7 min read
Save for later

Introducing RubyMotion and the Hello World app

Packt
22 Jul 2013
7 min read
(For more resources related to this topic, see here.) If you're reading this, you're either searching for an understanding of how RubyMotion can give you the keys to make iPhone, iPad, and OS X applications, or you're simply looking for further depth in your understanding of Ruby and Objective-C development. Either way, you're in the right place. To start this journey, we need to understand the basics of these two respected, but philosophically dissimilar, technologies and how a path has been beaten between them. Starting at the base, Apple development for iOS has traditionally been handled in Objective-C. Though Apple products have grown in popularity, Objective-C has not always been the first choice for application development. There's a long and torturous road of developers who have given up their app ambitions because of Objective-C. It is clear that for the greater part of over two decades, Objective-C has generally been the only programming language choice available for apps with Apple. Objective-C was made popular by Steve Jobs' company NeXT, for licensing Objective-C from StepStone in 1988. You'll often see evidence of this in the naming conventions of fundamental objects prefixed with NS for NeXTStep/Sun. This history renders the language a business decision as much as it was ever a developer-based decision. At the time Objective-C was licensed, the Ruby programming language was just an unnamed idea in Matz's head (Yukihiro "Matz" Matsumoto, inventor of Ruby). Objective-C has evolved, grown, and survived the test of time, but it ultimately remains verbose, without standardization, and programmatically rigid. In today's world, developers can afford to be opinionated with their programming language preferences, and a lot of them choose Ruby. Ruby is a standardized, dynamic, and general object-oriented programming language that takes inspiration from a long list of successful languages. Ruby is known to support a myriad of programming paradigms and is especially known for yielding elegant code. It's also often the cool programming language. Compared to the verbose and explicit nature of Objective-C, Ruby is a far cry and extremely opinionated language that programmers often adore. Let's take a moment to identify some core differences in the syntax of these two programming languages, starting with Objective-C. Objective-C is strongly typed. Counter to what some believe, strongly typed doesn't mean you hit the keys really hard, it means your variables have restrictions in their data types and how those variables can intermix. In Objective-C this is strictly checked and handled at compile time by a .hfile, the end result being that you're usually managing at least two files to make changes in one. Though you'll often find Objective-C methods to be long and capitalized in CamelCase, Ruby clashes with a Python-styled lowercase brevity. For example: Objective-C styled method SomeObject.performSomeMethodHere Ruby styled method SomeObject.some_method It's by no accident that I've shortened the method name in the preceding example. It's actually quite common for Objective-C to have long-winded method names, while, conversely Ruby methods are to be as short as possible, while maintaining the general intention of the method. Additionally, Ruby is more likely to sample functional and meta-programming aspects to make applications simple. So, if you're wondering which of these paradigms you will need to use and be accustomed to, the answer is both! I've seen a lot of RubyMotion code, and some people simply abandon their Ruby ways to try and make their code fit in with Objective-C libraries, all with great haste. But by far, the best method I've seen, and I highly recommend, is a mix. All Objective-C and Cocoa foundation framework objects should remain CamelCase, while all Ruby remains snake_case. At first glance this seems like twice the work, but it's really next to no effort at all, as your custom objects will be all written in Ruby by you. The advantage here is that upon examination, you can tell if a function, object, or variable should be looked up online on the Apple developer site (http://developer.apple.com/library/ios/navigation/) or if it should be searched for in a local code or Ruby code (http://www.ruby-doc.org/). I kind of wish I had this benefit with other Ruby languages, since I can instantly return to an older project and distinguish which code is purely mine and which is framework. Another key diff erence is the translation of code from messages to parameterized styling. I'm going to use some of the examples from RubyMotion.com to elaborate this issue. To properly convert the Objective-C: [string drawAtPoint:point withFont:font]; You will have to simply slide everything down to the left. The parameter to string is a method on it, and the rest become parameters. This yields the following code: string.drawAtPoint(point, withFont:font) Let's start with our Hello World app now. Have the controller in place so we can break away from the lifeless shell application and move more toward a true "Hello World" app. We won't need to deal with the AppDelegateany longer. Now we can start placing code in our controller. Remember when I said that this is a framework that calls into our code at given points, here's where we choose one of those points in time to hook into, and we'll choose one of the most common UIViewControllermethods, viewDidLoad. So, create a method called viewDidLoad, and let's put the following code inside: To find out what delegates are supported by any method and the order of method calls, you can look up the class reference of the object you are extending. For example, the documentation on the UIViewControllerclass' viewDidLoadcall is identified at http://developer.apple.com/library/ios/#documentation/uikit/reference/UIViewController_Class/Reference/Reference.html. Running your application at this point (by typing rakein the console) will cause your application to output "Hello World" to the application's standard output (the command line in this case). There's nothing too special happening here, we're using the traditional Ruby putsmethod to give us some feedback on the console. Running this does start the simulator. To quit the simulator, you can use command+ Q or from the console window, press Ctrl+ Dor Ctrl+ C. Since our phone doesn't really have a console to receive the standard output message, let's take this up a notch by adding a label to the application and configuring it to be a more traditional Hello World" on the device. So, we plan on making a label that will have the text "Hello World", correct? Let's create the test for that. We'll start by making a new file in our specfolder called hello_world_controller_spec.rband we'll make it look like the following: Let's inspect the testing code from the previous image. Everything looks similar to the other code but, as you can see, there's no need to make a beforeblock, since we are able to access the controller by simply stating the controller we're testing on the second line. This shortcut works for any ViewController you're testing! The actual testing and use for the variable starts with our specification. We grab the label so we can apply our two requirements on the following lines. We check the text value, and verify that the label has been added to the view. This might seem quite nebulous without knowing what we're testing, but the logic is simple. We want to make sure there's a label that says "Hello World" and we want it to be visible. Running these tests will fail, which puts us on track to write the actual "Hello World" portion. You should add the following code to your project's hello_world_controller.rbfile: Summary There it is! We've finally written a real Hello World application! Congratulations on your first RubyMotion application! You deserve it! Resources for Article : Further resources on this subject: Integrating Solr: Ruby on Rails Integration [Article] Building tiny Web-applications in Ruby using Sinatra [Article] Getting started with using Chef [Article]
Read more
  • 0
  • 0
  • 3568
article-image-article-integrating-ios-features-using-monotouch
Packt
13 Dec 2011
10 min read
Save for later

Integrating iOS Features Using MonoTouch

Packt
13 Dec 2011
10 min read
(For more resources on this topic, see here.) Mobile devices offer a handful of features to the user. Creating an application that interacts with those features to provide a complete experience to users can surely be considered as an advantage. In this article, we will discuss some of the most common features of iOS and how to integrate some or all of their functionality to our applications. We will see how to offer the user the ability to make telephone calls and send SMS and e-mails, either by using the native platform applications, or by integrating the native user interface in our projects. Also, we will discuss the following components: MFMessageComposeViewController: This controller is suitable for sending text (SMS) messagesIntegrating iOS Features MFMailComposeViewController: This is the controller for sending e-mails with or without attachments ABAddressBook: This is the class that provides us access to the address book database ABPersonViewController: This is the controller that displays and/or edits contact information from the address book EKEventStore: This is the class that is responsible for managing calendar events Furthermore, we will learn how to read and save contact information, how to display contact details, and interact with the device calendar. Note that some of the examples in this article will require a device. For example, the simulator does not contain the messaging application. To deploy to a device, you will need to enroll as an iOS Developer through Apple's Developer Portal and obtain a commercial license of MonoTouch. Starting phone calls In this recipe, we will learn how to invoke the native phone application to allow the user to place a call. Getting ready Create a new project in MonoDevelop, and name it PhoneCallApp. The native phone application is not available on the simulator. It is only available on an iPhone device. How to do it... Add a button on the view of MainController, and override the ViewDidLoad method. Implement it with the following code. Replace the number with a real phone number, if you actually want the call to be placed: this.buttonCall.TouchUpInside += delegate {  NSUrl url = new NSUrl("tel:+123456789012");  if (UIApplication.SharedApplication.CanOpenUrl(url)){    UIApplication.SharedApplication.OpenUrl(url);  }  else{    Console.WriteLine("Cannot open url: {0}", url.AbsoluteString);  }} ; Compile and run the application on the device. Tap the Call! button to start the call. The following screenshot shows the phone application placing a call: How it works... Through the UIApplication.SharedApplication static property, we have access to the application's UIApplication object. We can use its OpenUrl method, which accepts an NSUrl variable to initiate a call: UIApplication.SharedApplication.OpenUrl(url); Since not all iOS devices support the native phone application, it would be useful to check for availability frst: if (UIApplication.SharedApplication.CanOpenUrl(url))   When the OpenUrl method is called, the native phone application will be executed, and it will start calling the number immediately. Note that the tel: prefx is needed to initiate the call. There's more... MonoTouch also supports the CoreTelephony framework, through the MonoTouch. CoreTelephony namespace. This is a simple framework that provides information on call state, connection, carrier info, and so on. Note that when a call starts, the native phone application enters into the foreground, causing the application to be suspended. The following is a simple usage of the CoreTelephony framework: CTCallCenter callCenter = new CTCallCenter();callCenter.CallEventHandler = delegate(CTCall call) {  Console.WriteLine(call.CallState);} ;   Note that the handler is assigned with an equals sign (=) instead of the common plus-equals (+=) combination. This is because CallEventHandler is a property and not an event. When the application enters into the background, events are not distributed to it. Only the last occured event will be distributed when the application returns to the foreground. More info on OpenUrl The OpenUrl method can be used to open various native and non-native applications. For example, to open a web page in Safari, just create an NSUrl object with the following link: NSUrl url = new NSUrl("http://www.packtpub.com");   See also In this article: Sending text messages and e-mails Sending text messages and e-mails In this recipe, we will learn how to invoke the native mail and messaging applications within our own application. Getting ready Create a new project in MonoDevelop, and name it SendTextApp. How to do it... Add two buttons on the main view of MainController. Override the ViewDidLoad method of the MainController class, and implement it with the following code: this.buttonSendText.TouchUpInside += delegate {  NSUrl textUrl = new NSUrl("sms:");  if (UIApplication.SharedApplication.CanOpenUrl(textUrl)){    UIApplication.SharedApplication.OpenUrl(textUrl);  } else{    Console.WriteLine("Cannot send text message!");  }} ;this.buttonSendEmail.TouchUpInside += delegate {  NSUrl emailUrl = new NSUrl("mailto:");  if (UIApplication.SharedApplication.CanOpenUrl(emailUrl)){    UIApplication.SharedApplication.OpenUrl(emailUrl);  } else{    Console.WriteLine("Cannot send e-mail message!");  }} ; Compile and run the application on the device. Tap on one of the buttons to open the corresponding application. How it works... Once again, using the OpenUrl method, we can send text or e-mail messages. In this example code, just using the sms: prefx will open the native text messaging application. Adding a cell phone number after the sms: prefx will open the native messaging application: UIApplication.SharedApplication.OpenUrl(new NSUrl("sms:+123456789012"));     Apart from the recipient number, there is no other data that can be set before the native text message application is displayed. For opening the native e-mail application, the process is similar. Passing the mailto: prefx opens the edit mail controller. UIApplication.SharedApplication.OpenUrl(new NSUrl("mailto:"));     The mailto: url scheme supports various parameters for customizing an e-mail message. These parameters allows us to enter sender address, subject, and message: UIApplication.SharedApplication.OpenUrl("mailto:recipient@example.com?subject=Email%20with%20MonoTouch!&body=This%20is%20the%20message%20body!"); There's more... Although iOS provides access to opening the native messaging applications, pre-defning message content in the case of e-mails, this is where the control from inside the application stops. There is no way of actually sending the message through code. It is the user that will decide whether to send the message or not. More info on opening external applications The OpenUrl method provides an interface for opening the native messaging applications. Opening external applications has one drawback: the application that calls the OpenUrl method transitions to the background. Up to iOS version 3.*, this was the only way of providing messaging through an application. Since iOS version 4.0, Apple has provided the messaging controllers to the SDK. The following recipes discuss their usage. See also In this article: Starting phone calls Using text messaging in our application Using text messaging in our application In this recipe, we will learn how to provide text messaging functionality within our application using the native messaging user interface. Getting ready Create a new project in MonoDevelop, and name it TextMessageApp. How to do it... Add a button on the view of MainController. Enter the following using directive in the MainController.cs fle: using MonoTouch.MessageUI; Implement the ViewDidLoad method with the following code, changing the recipient number and/or the message body at your discretion: private MFMessageComposeViewController messageController;public override void ViewDidLoad (){  base.ViewDidLoad ();  this.buttonSendMessage.TouchUpInside += delegate {    if (MFMessageComposeViewController.CanSendText){      this.messageController = new          MFMessageComposeViewController();      this.messageController.Recipients = new          string[] { "+123456789012" };      this.messageController.Body = "Text from MonoTouch";      this.messageController.MessageComposeDelegate =          new MessageComposerDelegate();      this.PresentModalViewController(         this.messageController, true);    } else{      Console.WriteLine("Cannot send text message!");    }  } ;} Add the following nested class: private class MessageComposerDelegate :    MFMessageComposeViewControllerDelegate{  public override void Finished (MFMessageComposeViewController     controller, MessageComposeResult result){    switch (result){      case MessageComposeResult.Sent:        Console.WriteLine("Message sent!");      break;      case MessageComposeResult.Cancelled:        Console.WriteLine("Message cancelled!");      break;      default:        Console.WriteLine("Message sending failed!");      break;    }    controller.DismissModalViewControllerAnimated(true);  }} Compile and run the application on the device. Tap the Send message button to open the message controller. Tap the Send button to send the message, or the Cancel button to return to the application. How it works... The MonoTouch.MessageUI namespace contains the necessary UI elements that allow us to implement messaging in an iOS application. For text messaging (SMS), we need the MFMessageComposeViewController class. Only the iPhone is capable of sending text messages out of the box. With iOS 5, both the iPod and the iPad can send text messages, but the user might not have enabled this feature on the device. For this reason, checking for availability is the best practice. The MFMessageComposeViewController class contains a static method, named CanSendText, which returns a boolean value indicating whether we can use this functionality. The important thing in this case is that we should check if sending text messages is available prior to initializing the controller. This is because when you try to initialize the controller on a device that does not support text messaging, or the simulator, you will get the following message on the screen:   To determine when the user has taken action in the message UI, we implement a Delegate object and override the Finished method: private class MessageComposerDelegate :    MFMessageComposeViewControllerDelegate   Another option, provided by MonoTouch, is to subscribe to the Finished event of the MFMessageComposeViewController class. Inside the Finished method, we can provide functionality according to the MessageComposeResult parameter. Its value can be one of the following three: Sent: This value indicates that the message was sent successfully Cancelled: This value indicates that the user has tapped the Cancel button, and the message will not be sent Failed: This value indicates that message sending failed The last thing to do is to dismiss the message controller, which is done as follows: controller.DismissModalViewControllerAnimated(true);   After initializing the controller, we can set the recipients and body message to the appropriate properties: this.messageController.Recipients = new string[] { "+123456789012" };this.messageController.Body = "Text from MonoTouch";   The Recipients property accepts a string array that allows for multiple recipient numbers. You may have noticed that the Delegate object for the message controller is set to its MessageComposeDelegate property, instead of the common Delegate. This is because the MFMessageComposeViewController class directly inherits from the UINavigationController class, so the Delegate property accepts values of the type UINavigationControllerDelegate. There's more... The fact that the SDK provides the user interface to send text messages does not mean that it is customizable. Just like invoking the native messaging application, it is the user who will decide whether to send the message or discard it. In fact, after the controller is presented on the screen, any attempts to change the actual object or any of its properties will simply fail. Furthermore, the user can change or delete both the recipient and the message body. The real beneft though is that the messaging user interface is displayed within our application, instead of running separately. SMS only The MFMessageComposeViewController can only be used for sending Short Message Service (SMS) messages and not Multimedia Messaging Service (MMS).
Read more
  • 0
  • 0
  • 3561

article-image-how-use-jquery-mobile-grid-and-columns-layout
Packt
18 Jul 2011
6 min read
Save for later

How to Use jQuery Mobile Grid and Columns Layout

Packt
18 Jul 2011
6 min read
  jQuery Mobile First Look Discover the endless possibilities offered by jQuery Mobile for rapid Mobile Web Development Trying to communicate and provide information in an effective way can be a little trickier when we are targeting mobile devices; their screens are relatively small (ridiculously small if we think about our 24 inch iMac resting on our office desk), and we have already understood that we cannot display content in the way we used to, back in the days when desktop computers were the only way to access data on the Internet. With the advent of mobile browsing, new solutions had to be found. The jQuery Mobile framework provides a number of tools, widgets, and components which are extremely helpful in formatting our content and make it look elegant and put-together even on our beloved smaller-screen devices – well, especially for them! In fact, the difficulty in designing, formatting, and correctly showing a page on a mobile device is going to become a no-brainer using the set of elements jQuery Mobile provides in order to allow for an easy styling of our web application content. How content is displayed Yes, there is nothing wrong in just writing down what our website or web application is about in the HTML file. It's always worked and always will. The actual point here is taking advantage of the tools jQuery Mobile offers us to format our information, specifically for mobile devices. For example, there are occasions in which the need for multiple columns may arise: we can use a layout grid, which is nothing more than some CSS-based columns. Or, on a completely different note, we might just need to hide/show a block of content: collapsible blocks have been designed for this, and can be easily implemented in our site layout. But before we begin analyzing any of the methods in which we are able to format our content according to our liking, we should take a look at how content is displayed in its basic HTML formatting. Based upon the "light hand approach" (as they call it), jQuery Mobile lets the browser rendering take precedence over any other third-party styling, with exceptions made for the following little tweaks the framework applies to any page by default: Adding a bit of padding for a better readability Using the theming system to apply fonts and colors This particular approach to styling by default should make the designers really happy, as they often find themselves fighting with preset colors schemes, default fonts, weird margin, and padding values and usually end up resetting everything and starting again from scratch. Thankfully, the default padding value looks quite right and, as far as theming goes, we are able to easily customize (and create new) themes through CSS files and a theming framework which is extremely versatile and flexible. Default HTML markup styling So, what happens if we just write some HTML markup and want some text to be bold, emphasized, or hyper-linked? jQuery Mobile applies some basic styling to the elements and makes their look consistent with the simple and clean layout we have already seen in action. The following screenshot represents how headings and standard paragraphs are displayed and generated by the following code: <!DOCTYPE html> <html> <head> <title>Default HTML markup styling</title> <link rel="stylesheet" href="http://code.jquery.com/mobile/1.0a2/ jquery.mobile-1.0a2.min.css" /> <script src="http://code.jquery.com/jquery-1.4.3.min.js"></script> <script src="http://code.jquery.com/mobile/1.0a2/jquery.mobile- 1.0a2.min.js"></script> </head> <body> <div data-role="page" id="home"> <div data-role="content"> <h1>H1 Heading</h1> <h2>H2 Heading</h2> <h3>H3 Heading</h3> <h4>H4 Heading</h4> <h5>H5 Heading</h5> <h6>H6 Heading</h6> <p>This is a paragraph. <strong>Lorem (bold)</strong> <em>ipsum (emphasized)</em> <a href="#">dolor (link)</a> sit amet, consectetur adipiscing elit.</p> <blockquote>Blockquote containing a <cite>cite</cite></ blockquote> <p>This is a paragraph. <strong>Lorem (bold)</strong> <em>ipsum (emphasized)</em> <a href="#">dolor (link)</a> sit amet, consectetur adipiscing elit.</p> </div> </div> </body> </html> The result is shown in the following screenshot: Similarly, the following code produces a preview of what lists and tables look like: <!DOCTYPE html> <html> <head> <title>Default HTML markup styling</title> <link rel="stylesheet" href="http://code.jquery.com/mobile/1.0a2/ jquery.mobile-1.0a2.min.css" /> <script src="http://code.jquery.com/jquery-1.4.3.min.js"></script> <script src="http://code.jquery.com/mobile/1.0a2/jquery.mobile- 1.0a2.min.js"></script> </head> <body> <div data-role="page" id="home"> <div data-role="content"> <ul> <li>Unordered list item 1</li> <li>Unordered list item 2</li> <li>Unordered list item 3</li> </ul> <ol> <li>Ordered list item 1</li> <li>Ordered list item 2</li> <li>Ordered list item 3</li> </ol> <table> <caption>Table caption</caption> <thead> <tr> <th scope="col">Name</th> <th scope="col">City</th> <th scope="col">Phone</th> </tr> </thead> <tfoot> <tr> <td colspan="5">Table foot</td> </tr> </tfoot> <tbody> <tr> <th scope="row">David Green</th> <td>New York City, NY</td> <td>555-0123</td> </tr> <tr> <th scope="row">Martha White</th> <td>Los Angels, CA</td> <td>555-0188</td> </tr> <tr> <th scope="row">Bobby Brown</th> <td>Washington, D.C.</td> <td>555-0110</td> </tr> </tbody> </table> </div> </div> </body> </html>
Read more
  • 0
  • 0
  • 3506

Packt
31 Dec 2013
5 min read
Save for later

Geolocation – using PhoneGap features to improve an app's functionality, write once use everywhere

Packt
31 Dec 2013
5 min read
(For more resources related to this topic, see here.) Step 1 – define global variables We include the following variables and functions in our file: var map; var latitud; var longitud; var xmlDoc = loadXml("puntos.xml"); var marker; var markersArray = []; function loadXml(xmlUrl) { var xmlhttp; if (window.XMLHttpRequest) { xmlhttp = new XMLHttpRequest(); } else { xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); } xmlhttp.open("GET", xmlUrl, false); xmlhttp.send(); xmlDoc = xmlhttp.responseXML; return xmlDoc; } With this code, we build our first function called loadXmlthat just loads the information into the XML file and then in to the smart phone memory. Step 2 – get current position We will build the following functions that we need to show our current position in Google Maps: getCurrentPosition: This function receives an object with the latitude and longitude. These values are set to two variables defined as global variables with the same name. This function receives three parameters, which are as follows: A function to manage the current latitude and longitude A function to manage errors if they occur when the device is trying to get the position Options to configure maximumAge: This is the time required to keep our position on the cache in milliseconds timeout: This is the maximum time required to wait for an answer from the getCurrentPosition function in milliseconds enableHighAccuracy: This provides a more accurate location The values of these functions can be set to either True or False. The following is the code for the preceding functions: getCurrentPosition(coordinates, errors, { maximumAge : 3000, timeout : 15000, enableHighAccuracy : true } The following is the code for the coordinates and errors functions: function coordinates(position) { latitud = position.coords.latitude; /* saving latitude */ longitud = position.coords.longitude; /* saving longitude*/ loadMap(); }// end function function errors(err) { /* Managing errors */ if (err.code == 0) { alert("Oops! Something is wrong"); } if (err.code == 1) { alert("Oops! Please accept share your position with us."); } if (err.code == 2) { alert("Oops! We can't get your current position."); } if (err.code == 3) { alert("Oops! Timeout!"); } }// end errors LocateMe: This function checks whether the device supports the PhoneGap geolocalization API or not. If the device supports the API, then this function calls a method to obtain the current position. If the device doesn't support geolocalization API, then we will use the current position's function, getCurrrentPosition, explained previously. The complete code for the LocateMe function is as follows: function locateMe() { if (navigator.geolocation) { /* The browser have geolocalization */ navigator.geolocation.getCurrentPosition(coordinates, errors, { maximumAge : 3000, timeout : 15000, enableHighAccuracy : true }); } else { alert('Oops! Your browser doesn't support geolocalization'); } } Step 3 – showing the current position using Google Maps To do this, we use a function that we called loadMap. This function is responsible for loading a map using Google Maps API with the current position. Also, we use a JavaScript object called myOptions with three properties, zoom to define the zoom, center to define where the maps will be centered, and mapTypeId to indicate the map style (that is Satellite). Following the code, we find two lines: the first one initializes the actualHeight variable according to the value that is returned by the getActualContentHeight function. This function returns the height that the map needs to have according to the screen size. In the second line, we change the height of the div "map canvas" through the jQuery Mobile method's CSS. In the following code file, we set the variable map with the google.maps.Map object that receives the parameters, the HTML element, and the myOptions object. We use an additional event to resize the map when the screen size changes. Now, we create a new marker object google.maps.Marker with four properties: position for the place of the marker, map that is the global variable, icon to define the image that we want to use as a marker, and the tooltip with the property title. We have two functions: the first one is createMarkers that allows us to read the XML file with the points uploaded in memory and, after that, puts the markers in the map with our second function addMarker that receives four parameters (the global map variable, point name, address and phone, and the google.maps.LatLng object with the point coordinates) to build the marker. We add a click event to show all the information about the place. Finally, we use the removePoints function that clears the maps, thereby deleting the points loaded. This is the code for the JS file: function loadMap() { var latlon = new google.maps.LatLng(latitud, longitud); var myOptions = { zoom : 17, center : latlon, mapTypeId : google.maps.MapTypeId.ROADMAP }; map = new google.maps.Map(document.getElementById('map_canvas'), myOptions); var mapDiv = document.getElementById('map_canvas'); google.maps.event.addDomListener(mapDiv, 'resize', function(){ google.maps.event.trigger(map,'resize'); }); var coorMarker = new google.maps.LatLng(latitud, longitud); marker = new google.maps.Marker({/* Create the marker */ position : coorMarker, map : map, icon : 'images/green-dot.png', title : "Where am I?" }); } Step 4 – edit the HTML file To implement the preceding functions, we need to add some code lines in our HTML file. We need to add the script line to include the new JS file, and add a complete JavaScript in the HTML head tag to execute the locateMe function. Now that the device is ready, another PhoneGap function calls watchPosition to update the position when the user is moving. Summary This article has shown us how to implement Geolocation in our app. It also shows how to use the API provided by PhoneGap to use in our app. The code for pointing out our current location was also discussed. Resources for Article: Further resources on this subject: Using Location Data with PhoneGap [Article] Configuring the ChildBrowser plugin [Article] Creating and configuring a basic mobile application [Article]
Read more
  • 0
  • 0
  • 3494
article-image-various-components-sencha-touch
Packt
16 Feb 2012
8 min read
Save for later

The Various Components in Sencha Touch

Packt
16 Feb 2012
8 min read
  (For more resources on this topic, see here.) The reader can benefit from the previous article on Sencha Touch: Layouts Revisited. The TabPanel and Carousel components In our last application, we used buttons and a card layout to create an application that switched between different child items. While it is often desirable for your application to do this programmatically (with your own buttons and code), you can also choose to have Sencha Touch set this up automatically, using TabPanel or Carousel. TabPanel TabPanel is useful when you have a number of views the user needs to switch between, such as, contacts, tasks, and settings. The TabPanel component autogenerates the navigation for the layout, which makes it very useful as the main container for an application. The following is a code example: new Ext.Application({ name: 'TouchStart', launch: function() { this.viewport = new Ext.TabPanel({ fullscreen: true, cardSwitchAnimation: 'slide', tabBar:{ dock: 'bottom', layout: { pack: 'center' } }, items: [{ xtype: 'container', title: 'Item 1', fullscreen: false, html: 'TouchStart container 1', iconCls: 'info' }, { xtype: 'container', html: 'TouchStart container 2', iconCls: 'home', title: 'Item 2' }, { xtype: 'container', html: 'TouchStart container 3', iconCls: 'favorites', title: 'Item 3' }] }); }}); TabPanel, in this code, automatically generates a card layout; you don't have to declare a layout. You do need to declare a configuration for the tabBar component. This is where your tabs will automatically appear. In our previous code example, we dock the toolbar at the bottom. This will generate a large square button for each child item in the items list. The button will also use the iconCls value to assign an icon to the button. The title configuration is used to name the button. If you dock the tabBar component at the top, it makes the buttons small and round. It also eliminates the icons, even if you declare a value for iconCls, in your child items. Only the title configuration is used when the bar is docked at the top. Carousel The Carousel component is similar to TabPanel, but the navigation it generates is more appropriate for things such as slide shows. It probably would not work as well as a main interface for your application, but it does work well as a way to display multiple items in a single swipeable container. Similar to TabPanel, Carousel gathers its child items and automatically arranges them in a card layout. In fact, we can actually make just some simple modifications to our previous code to make it into a Carousel: new Ext.Application({ name: 'TouchStart', launch: function() { this.viewport = new Ext.Carousel({ fullscreen: true, direction: 'horizontal', items: [{ html: 'TouchStart container 1' }, { html: 'TouchStart container 2' }, { html: 'TouchStart container 3' }] }); }}); The first thing we did was create a new Ext.Carousel class instead of a new Ext.TabPanel class. We also added a configuration for direction, which can be either horizontal (scrolling from left to right) or vertical (scrolling up or down). We removed the docked toolbar, because, as we will see, Carousel doesn't use one. We also removed iconClass and title from each of our child items for the same reason. Finally, we removed the xtype configuration, since the Carousel automatically creates a panel for each of its items. Unlike TabPanel, Carousel has no buttons, only a series of dots at the bottom, with one dot for each child item. While it is possible to navigate using the dots, the Carousel component automatically sets itself up to respond to a swipe on a touch screen. You can duplicate this gesture in the browser by clicking and holding with the mouse, while moving it horizontally. If you declare a direction: vertical configuration in your Carousel, you can swipe vertically, to move between the child items. TabPanel and the Carousel components understand the activeItem configuration. This lets you set which item appears when the application first loads. Additionally, they all understand the setActiveItem() method that allows you to change the selected child item after the application loads. Carousel also has methods for next() and previous(), which allow you to step through the items in order. It should also be noted that, since TabPanel and Carousel both inherit from the panel, they also understand any methods and configurations that panels and containers understand. Along with containers and panels, TabPanel and Carousel will serve as the main starting point for most of your applications. However, there is another type of panel you will likely want to use at some point: the FormPanel.   FormPanel The FormPanel panel is a very specialized version of the panel, and as the name implies, it is designed to handle form elements. Unlike panels and containers, you don't need to specify the layout for FormPanel. It automatically uses its own special form layout. A basic example of creating a FormPanel would look something like this: var form = new Ext.form.FormPanel({ items: [ { xtype: 'textfield', name : 'first', label: 'First name' }, { xtype: 'textfield', name : 'last', label: 'Last name' }, { xtype: 'emailfield', name : 'email', label: 'Email' } ]}); For this example, we just create the panel and add items for each field in the form. Our xtype tells the form what type of field to create. We can add this to our Carousel and replace our first container, as follows: this.viewport = new Ext.Carousel({ fullscreen: true, direction: 'horizontal', items: [form, { layout: 'fit', html: 'TouchStart container 2' }, { layout: 'fit', html: 'TouchStart container 3' }]}); Anyone who has worked with forms in HTML should be familiar with all of the standard field types, so the following xtype attribute names will make sense to anyone who is used to standard HTML forms: checkboxfield fieldset hiddenfield passwordfield radiofield selectfield textfield textareafield These field types all match their HTML cousins, for the most part. Sencha Touch also offers a few specialized text fields that can assist with validating the user's input: emailfield - Accepts only a valid e-mail address, and on iOS devices, will pull up an alternate e-mail address and URL-friendly keyboard numberfield - Accepts only numbers urlfield - Accepts only a valid web URL, and also brings up the special keyboard These special fields will only submit if the input is valid. All of these basic form fields inherit from the main container class, so they have all of the standard height, width, cls, style, and other container configuration options. They also have a few field-specific options: label - A text label to use with the field labelAlign - Where the label appears; this can be top or left, and defaults to left labelWidth - How wide the label should be name - This corresponds to the HTML name attribute, which is how the value of the field will be submitted maxLength - How many characters can be used in the field required - If the field is required in order for the form to submit Form field placement While FormPanel is typically the container you will use when displaying form elements, you can also place them in any panel or toolbar, if desired. FormPanel has the advantage of understanding the submit() method that will post the form values via AJAX request or POST. If you include a form field in something that is not a FormPanel, you will need to get and set the values for the field using your own custom JavaScript method. In addition to the standard HTML fields, there are a few specialty fields available in Sencha Touch. These include the datepicker, slider, spinner, and toggle fields. DatePicker datepickerfield places a clickable field in the form with a small triangle on the far right side. You can add a date picker to our form by adding the following code after the emailfield item: ,{ xtype: 'datepickerfield', name : 'date', label: 'Date'} When the user clicks the field, a DatePicker will appear, allowing the user to select a date by rotating the month, day, and year wheels, by swiping up or down. Sliders, spinners, and toggles Sliders allow for the selection of a single value from a specified numerical range. The sliderfield value displays a bar, with an indicator, that can be slid horizontally to select a value. This can be useful for setting volume, color values, and other ranged options. Like the slider, a spinner allows for the selection of a single value from a specified numerical range. The spinnerfield value displays a form field with a numerical value with + and - buttons on either side of the field. A toggle allows for a simple selection between one and zero (on and off) and displays a toggle-style button on the form. Add the following new components to the end of our list of items: ,{ xtype : 'sliderfield', label : 'Volume', value : 5, minValue: 0, maxValue: 10},{ xtype: 'togglefield', name : 'turbo', label: 'Turbo'},{xtype: 'spinnerfield',minValue: 0,maxValue: 100,incrementValue: 2,cycle: true} The following screenshot shows how the new components will look: Our sliderfield and spinnerfield have configuration options for minValue and maxValue. We also added an incrementValue attribute, to spinnerfield, that will cause it to move in increments of 2 whenever the + or - button is pressed.  
Read more
  • 0
  • 0
  • 3491

article-image-basic-security-approaches
Packt
19 Sep 2013
10 min read
Save for later

Basic Security Approaches

Packt
19 Sep 2013
10 min read
(For more resources related to this topic, see here.) Security, privacy, and safeguards for intellectual property are at the front of the minds of those of us building Titanium Enterprise apps. Titanium allows you to combine the underlying platform tools and third-party JavaScript libraries to help meet your security requirements. This article provides a series of approaches on how to leverage JavaScript, Titanium modules, and the underlying platform to enable you to create a layered security approach to assist you in meeting your organization's overall secure development goals. Each recipe is designed to provide building blocks to help you implement your industry's existing security and privacy standards. Implementing iOS data protection in Titanium Starting with iOS 4, Apple introduced the ability for apps to use the data protection feature to add an additional level of security for data stored on disk. Data protection uses the built-in hardware encryption to encrypt files stored on the device. This feature is available when the user's device is locked and protected with a passcode lock. During this time, all files are protected and inaccessible until the user explicitly unlocks the device. When the device is locked, no app can access protected files. This even applies to the app that created the file. Getting ready This recipe uses the securely native module for enhanced security functionality. This module and other code assets can be downloaded from the source provided by the book. Installing these in your project is straightforward. Simply copy the modules folder into your project as shown in the following screenshot: After copying the mentioned folder, you will need to click on your tiapp.xml file in Titanium Studio and add a reference to the bencoding.securely module as shown in the following screenshot: Enabling data protection This recipe requires your iOS device to have data protection enabled. You will need a device as the simulator does not support data protection. The following steps cover how to enable this feature on your device: Go to Settings | General | Passcode . Follow the prompts to set up a passcode. After adding a passcode, scroll to the bottom of the screen and verify that the text Data protection is enabled is visible as shown in the following screenshot: iOS device browser A third-party iOS device browser is needed to verify that data protection for the example recipe app has successfully been enabled. This recipe discusses how to verify data protection using the popular iExplorer app. An evaluation version of the iExplorer app can be used to follow along with this recipe. For more information and to download iExplorer, please visit http://www.macroplant.com/iexplorer. How to do it... To enable iOS data protection, the DataProtectionClass and com.apple.developer.default-data-protection keys need to be added to your tiapp.xml as demonstrated in the following code snippet: First, add the ios configuration node if your project does not already contain this element. <ios> <plist> <dict> Then at the top of the dict node, add the following highlighted keys. <key>DataProtectionClass</key> <string>NSFileProtectionComplete</string> <key>com.apple.developer. default-data-protection</key> <string>NSFileProtectionComplete</string> </dict> </plist> </ios>   After saving the updates to your tiapp.xml, you must clean your Titanium project in order to have the updates take effect. This can be done in Titanium Studio by selecting Project | Clean . Creating the namespace and imports Once you have added the securely module and added the tiapp.xml updates to your project, you need to create your application namespace in the app.js file and use require to import the module into your code as the following code snippet demonstrates: //Create our application namespace var my = { secure : require('bencoding.securely') }; Creating the recipe UI The following steps outline how to create the UI used in this recipe: First, a Ti.UI.Window is created to attach all UI elements. var win = Ti.UI.createWindow({ backgroundColor: '#fff', title: 'Data Protection Example', barColor:'#000',layout:'vertical' }); Next, a Ti.UI.Button is added to the Ti.UI.Window. This will be used to trigger our example. var button1 = Ti.UI.createButton({ title:'Create Test File', top:25, height:45, left:5, right:5 }); win.add(button1); Creating a file to verify data protection To verify if data protection is enabled in the app, the recipe creates a time-stamped file in the Ti.Filesystem.applicationDataDirectory directory. Using an iOS device browser, we can verify if the test file is protected when the device is locked. The following steps describe how the recipe creates this test file: The click event for button1 creates a time-stamped file that allows us to verify if data protection has been correctly enabled for the app. button1.addEventListener('click',function(e){ Next the isProtectedDataAvailable method is called on securely. This provides a Boolean result indicating that data protection allows the app to read from or write to the filesystem. if(!my.secure.isProtectedDataAvailable()){ alert('Protected data is not yet available.'); return; } To ensure there is a unique identifier in the file, a token is created using the current date and time. This token is then added to the following message template: var timeToken = String.formatDate(new Date(),"medium") + String.formatTime(new Date()); var msg = "When device is locked you will not be able"; msg += " to read this file. Your time token is "; msg += timeToken; The message created in step 3 is then written to the test.txt file located in the Ti.Filesystem.applicationDataDirectory directory. If the file already exists, it is removed so that the latest message will be available for testing. var testfile = Ti.Filesystem.getFile( Ti.Filesystem.applicationDataDirectory, 'test.txt'); if(testfile.exists()){ testfile.deleteFile(); } testfile.write(msg); testfile = null; Once the test.txt file is written to the device, a message is displayed to the user notifying them to lock their device and use an iOS device browser to confirm data protection is enabled. var alertMsg = "Please lock your device."; alertMsg+= "Then open an iOS Device Browser."; alertMsg+= "The time token you are looking for is "; alertMsg+= timeToken; alert(alertMsg); How it works... After the DataProtectionClass and com.apple.developer.default-data-protection keys have been added to your tiapp.xml, the iOS device handles protecting your files when the device is locked. The following steps discuss how to test that this recipe has correctly implemented data protection: The first step in the validation process is to build and deploy the recipe app to your iOS device. Once the app has been loaded onto your device, open the app and press the Create Test File button. Once you have received an alert message indicating the test file has been created, press the home button and lock your device. Plug your device into a computer with iExplorer installed. Open iExplorer and navigate so that you can view the apps on your device. Select the DataProtection app as marked with the red box in the following screenshot. Then right-click on the test.txt file located in the Documents folder and select Quick Look as marked with the green box in the following screenshot: After Quick Look is selected, iExplorer will try to open the test.txt file. Since it is protected, it cannot be opened and Quick Look will show the progress indicator until a timeout has been reached. You can then unlock your device and repeat the preceding steps to open the file in Quick Look . AES encryption using JavaScript The Advanced Encryption Standard ( AES ) is a specification for the encryption of electronic data established by the U.S. NIST in 2001. This encryption algorithm is used for securing sensitive, but unclassified material by U.S. Government agencies. AES has been widely adopted by enterprise and has become a de facto encryption standard for many commercially sensitive transactions. This recipe discusses how AES can be implemented in JavaScript and incorporated into your Titanium Enterprise app. Getting ready This recipe uses the Ti.SlowAES CommonJS module as a wrapper around the SlowAES open source project. Installing these in your project is straightforward. Simply copy the SlowAES folder into the Resources folder of your project as shown in the following screenshot: How to do it... Once you have added the SlowAES folder to your project, next you need to create your application namespace in the app.js file and use require to import the module into your code as the following code snippet demonstrates: //Create our application namespace var my = { mod : require('SlowAES/Ti.SlowAES') }; Creating the recipe UI This recipe demonstrates the usage of the Ti.SlowAES CommonJS module through a sample app using two Ti.UI.TextField controls for input. First, a Ti.UI.Window is created to attach all UI elements. var win = Ti.UI.createWindow({ backgroundColor: '#fff', title: 'AES Crypto Example', barColor:'#000',layout:'vertical',fullscreen:false }); Next, a Ti.UI.TextField control is added to the Ti.UI.Window to gather the secret from the user. var txtSecret = Ti.UI.createTextField({ value:'DoNotTell',hintText:'Enter Secret', height:45, left:5, right:5, borderStyle:Ti.UI.INPUT_BORDERSTYLE_ROUNDED }); win.add(txtSecret); Another Ti.UI.TextField is added to the Ti.UI.Window to gather the string to encrypt from the user. var txtToEncrypt = Ti.UI.createTextField({ value:'some information we want to encrypt', hintText:'Enter information to encrypt', height:45, left:5, right:5, borderStyle:Ti.UI.INPUT_BORDERSTYLE_ROUNDED }); win.add(txtToEncrypt); Next a Ti.UI.Label is added to the Ti.UI.Window. This Ti.UI.Label will be used to display the encrypted value to the user. var encryptedLabel = Ti.UI.createLabel({ top:10, height:65, left:5, right:5,color:'#000', textAlign:'left',font:{fontSize:14} }); win.add(encryptedLabel); Finally a Ti.UI.Button is added to the Ti.UI.Window. This Ti.UI.Button will be used later in the recipe to perform the encryption test. var btnEncrypt = Ti.UI.createButton({ title:'Run Encryption Test', top:25, height:45, left:5, right:5 }); win.add(btnEncrypt); Encrypting and decrypting values This section demonstrates how to use the Ti.SlowAES module to use the secret entered in the txtSecret, Ti.UI.TextField to encrypt the contents of the txtToEncrypt, Ti.UI.TextField. Once completed, the encrypted value is then decrypted and compared against the original input. The results are displayed to the user in an alert message as shown in the following screenshots: The encryption test is performed when the click event for the btnEncrypt control is fired as shown in the following code snippet: btnEncrypt.addEventListener('click',function(x){ The first step in the encryption process is to create a new instance of the SlowAES module as shown in this code snippet. var crypto = new my.mod(); Next using the encrypt function, the secret provided in the txtSecret control is used to encrypt the value in the txtToEncrypt control. The encrypted results are then returned to the encryptedValue as demonstrated in the following statement: var encryptedValue = crypto.encrypt(txtToEncrypt.value,txtSecret.value); The encryptedLabel.text property is then updated to display the encrypted value to the user. encryptedLabel.text = 'Encrypted:' + encryptedValue; Next, the decrypt method is used to demonstrate how to decrypt the string value encrypted earlier. This method requires the encrypted string value and the secret as shown in the following snippet: var decryptedValue = crypto.decrypt(encryptedValue,txtSecret.value); Finally, the original input value is compared against the decrypted value to ensure our encryption test was successful. The results of this test are then displayed to the user through a message alert and the Titanium Studio console. alert((txtToEncrypt.value ===decryptedValue) ? 'Encryption Test successfully ran check console for details.': 'Test failed, please check console for details.'); });
Read more
  • 0
  • 0
  • 3442
Modal Close icon
Modal Close icon