Category Archives: iPhone

Create applications for iPhone and iPad using Phonegap, Titanium Appcelerator and other frameworks. News, opinions and interesting apps.

day7

Seven days with Titanium – day 7 – orientation and accelerometer

Most of the devices nowadays are equipped with an accelerometer that detect the orientation of the device or the movements the user is doing with it.

Titanium exposes this functionality through its APIs so let’s take advantage of that :)

The orientation

The device can report 7 states of the orientation and they are defined in Titanium as follows:

  • Ti.UI.UNKNOWN – the app cannot detect the position
  • Ti.UI.PORTRAIT
  • Ti.UI.UPSIDE_PORTRAIT
  • Ti.UI.LANDSCAPE_LEFT
  • Ti.UI.LANDSCAPE_RIGHT
  • Ti.UI.FACE_DOWN – like resting on a table with the screen downward
  • Ti.UI.FACE_UP – like resting on a table but with the screen upward

While we have all this constants defined there are situations where they might not be available: in iOs when the user locks the orientation the device will report that orientation no matter how the device is held. On Android many devices can detect only the PORTRAIT and LANDSCAPE_LEFT orientations.

Since version 1.7.2 of the SDK the orientation API changed and is set per window (or activity). You can do this using the property orientationModes that accepts an array with the allowed orientation for that window. See this post on Appcelerator’s blog.

win.orientationModes = [Ti.UI.PORTRAIT, Ti.UI.LANDSCAPE_RIGHT];

There is also an event that triggers when the orientation changes allowing you to make the changes you might need (adapt the UI to the new orientation for example.)

Ti.Gesture.addEventListener('orientationchange',function(e) {
    alert(e.orientation);
});

The alert will show a number from 1 to 7 because the constants defined above are type INT. A good practice is to compare the orientation reported by the event with the constant and not directly with the number. In case something will change in the future this will assure you that the code will keep working.

You can find more about it in the docs page for Titanium.Gesture

The accelerometer

The accelerometer is a piece of hardware that is giving you the current position of the device in a 3D coordinates (x, y and z) vector. This can allow you for example to control the movements of an element on the screen.

To get this vector all you have to do is to catch the update event of the Titanium.Accelerometer APIs. It will return the vector we were talking about.

Ti.Accelerometer.addEventListener('update', function(e) {
    lbl.text = 'x: ' + e.x + 'y:' + e.y + 'z:' + e.z;
});

Again, it’s a good practice to remove the event when we don’t need it anymore to save some CPU cycles :)

Well, that’s it for Day 7. Code strong!

bonjour-titanium-mobile

Advanced Titanium Tutorial – Bonjour Networking

Titanium Appcelerator Mobile has implemented for iOs the Bonjour (or ZeroConf if you want) network protocol that allows you to connect to another device found in the same network.

Before starting with the boring part – I mean the code – let’s watch a video with a small demo showing 3 devices playing together :)

Networking with Titanium Mobile on iOs

I would like to mention that the iPod is a second generation one – so less capable (the delays are visible in the video) and somehow, sometimes, even seems to loose packets. I tested the same app with an iPad instead of the iPod and everything works just fine.
bubbles

Bonjour

Based on the code found in KitchenSink I created a small function that creates the connection for us and returns an object to allow you to start it, close it and write to the socket.

Bonjour is a little weird to understand for those with less experience but shortly, things are like this:

  • We need a socket in read-write mode that will be used by a localService to publish its presence.
  • Each localService have to have its own unique name to be able to identify it in the network.

Besides this, we need a serviceBrowser to find other devices around (that published their presence, of course).

Since everything is asynchronous we’ll have to rely on events to capture the data sent by somebody or the changes in the number of devices connected.

The serviceBrowser has the updatedServices event where we can capture the published services. Here in this function we’ll try to catch the read event for each service that is the one who tells us what data is sent over the network.

Warning: Close the network connection the moment you don’t need it anymore.

The Network Connection Function

The function I created takes care of this so you will just have to use it as in the example below:

Titanium.include('bj.js');
 
var connection = bjnet('my_unique_name', function(data){
	var json_data = JSON.parse(data);
	//do something with this data;
});
 
connection.start();

In other point of your app, where you want to send over a message, just do:

	connection.write('my_message');

As I said before, don’t forget to clean everything:

win.addEventListener('close', function(e) {
	connection.stop();
});

What is going on in the demo?

The example in the video is pretty simple. Depending on what blob you touch (red, green or blue) you create a new connection with this name and start it. At this moment any message coming from the network is JSON parsed and a small blob is created with the specified coordinates and color.

On your turn, when you touch the screen you send over the network your coordinates and color so the other devices know what to draw. Every message is a JSON stringified object like the one below:

	{coords:{x:100,y:200},player:{name:'red', color:'#f00'}}

As an aside the demo uses zero images. None. Everything is native and I plan a future tutorial on how to do this :)

The code

The code is hosted on Github and you can download it from here. Everything is MIT licensed but I’d like to hear what you come up with.

Code strong!

PS. I’m allowed to say this cause I’m a titan 😀

Check the Spanish version of this post:
Tutorial Avanzado de Titanium – Bonjour Networking

day6

Seven days with Titanium – day 6 – animations and transforms

Almost any UI element can be animated and transformed, allowing you to add to your application some eye candy or simply take advantage of predefined elements to give them a new role. For those familiar with CSS3 animations this will come very easy as the concept it’s pretty the same.

Animations

Pointless to say, an animation will change one or more properties of an element form the current stage to another (set by us) in a period of time.

var my_view =  Titanium.UI.createView({
    backgroundColor:'#f00',
    height:20
});
my_view.animate({height:100});

The simple code above will animate the height of my_view from 20 to 100.

You can complicate the things more adding more properties to animate (like the background color, opacity, etc), a duration (that needs to be in ms) and a curve (like ease-out or liniar, etc)

Some examples

var view = Titanium.UI.createView({
	width:100,
	height:20,
	backgroundColor:'#f00'
});
 
win.add(view);
 
view.animate({
	height:300, 
	backgroundColor:'#00f', 
	duration:3000, 
	curve:Titanium.UI.ANIMATION_CURVE_EASE_IN_OUT
});

If you need to make an animation to come back to the element’s original state and repeat it several times, there are 2 properties that might interest you :repeat and autoreverse

The below code will make the view “pulse” 3 times.

var view = Titanium.UI.createView({
	width:100,
	height:100,
	backgroundColor:'#f00'
});
 
win.add(view);
 
view.animate({
	height:130,
	width:130,
	repeat:3,
	autoreverse:true,
	curve:Titanium.UI.ANIMATION_CURVE_EASE_IN_OUT
});

The animations have 2 events: start and complete.The complete event is very useful because we can chain more animations one after another or start some other actions when the current one stops.

Transforms

Similar to CSS3 transforms, in Titanium you can use 2D or 3D transforms.

Basically you create a 2D or a 3D matrix for the transform or use the predefined “shortcuts” – (like scale or rotate) and pass this transform to the object you are creating or to the animation.

An example with transforms

var tr_start = Titanium.UI.create2DMatrix();
tr_start = tr_start.rotate(30);
 
var tr_end = Titanium.UI.create2DMatrix();
tr_end = tr_end.rotate(-30);
tr_end = tr_end.scale(2);
 
var view = Titanium.UI.createView({
	width:100,
	height:100,
	transform:tr_start,
	backgroundColor:'#f00',
});
 
win.add(view);
 
view.animate({
	transform:tr_end,
	repeat:3,
	autoreverse:true,
	duration:500,
	curve:Titanium.UI.ANIMATION_CURVE_EASE_IN_OUT
});

The best resources to see how everything works are the examples provided by the Appcelerator team in the KitchenSink, the entry point being here:http://bit.ly/eiow0B

These animations and transforms are not suited to a very intensive usage (like games) but they can be used with success to improve the apps’ look and feel – and with this, the user experience.

As always, I wait for your questions, suggestions and what are you come up with :)
Check the Spanish version of this post:
Siete días con Titanium – día 6 – animaciones y transformaciones

day5

Seven days with Titanium – day 5 – GPS and Maps

This doesn’t need any kind of introduction. You can use the location on the devices to find the user’s place and act accordingly. One thing good to know is that this needs the approval of the user, and for iOs > 3.2 you need to set a purpose property to let Apple know what you need it for.

Titanium.Geolocation.purpose = "GPS user coordinates";

How geolocation works

When you start the app the coordinates are the ones cached on the device, in other words the ones detected at the last time you used the geolocation on your device. Detecting the current position takes time so if you have an app based on geolocation you might want to take this in account to improve the user experience and avoid to get false results.

Titanium.Geolocation provides the needed methods to manage geolocation.

In general the most used method is getCurrentPosition that gives you the current position and fires once and the location event that triggers repeatedly on the location change. To be more clear think you want to log a route the user follow: when the app starts you get its start position then while walking you can get the points of the route with a adjustable granularity.

 
Titanium.Geolocation.distanceFilter = 10; // set the granularity of the location event
 
	Titanium.Geolocation.getCurrentPosition(function(e)
	{
		if (e.error)
		{
                // manage the error
                return;
		}
 
		var longitude = e.coords.longitude;
		var latitude = e.coords.latitude;
		var altitude = e.coords.altitude;
		var heading = e.coords.heading;
		var accuracy = e.coords.accuracy;
		var speed = e.coords.speed;
		var timestamp = e.coords.timestamp;
		var altitudeAccuracy = e.coords.altitudeAccuracy;
 
                // we use the above data the way we need it
	});
 
	Titanium.Geolocation.addEventListener('location',function(e)
	{
		if (e.error)
		{
                // manage the error
		return;
		}
 
		var longitude = e.coords.longitude;
		var latitude = e.coords.latitude;
		var altitude = e.coords.altitude;
		var heading = e.coords.heading;
		var accuracy = e.coords.accuracy;
		var speed = e.coords.speed;
		var timestamp = e.coords.timestamp;
		var altitudeAccuracy = e.coords.altitudeAccuracy;
 
               // again we use the gathered data
      });

There are some other methods that can be used like reverseGeocoder, forwardGeocoder, and getCurrentHeading – for compass. Because not all the devices have the GPS location (like iPod) or the compass and because the user can have the location services disabled you have to check if it exists, if it’s enabled and then let the user know about this.

As the documentation page is not complete yet, I suggest you to take a look at the geolocation example that shows very well how to use this.

Maps

The maps are created using the Titanium.Map methods. The maps are a little bit complicated but allows you to do some real nice interfaces. You can use a Mapview and add a route to it, or pins(markers) and to the pins to attach popups with images, titles, even “links” o another windows for a more detailed view of the specified place or whatever you may need.

Create a map

var mapview = Titanium.Map.createView({
	top:20,
	height:300,
	mapType: Titanium.Map.STANDARD_TYPE,
	region:{latitude:33.74511, longitude:-84.38993, latitudeDelta:0.5, longitudeDelta:0.5},
	animate:true,
	regionFit:true,
	userLocation:true
});

Nothing complicated: the constructor can receive different arguments including the annotations (pins), but of course you will have to declare it first.

And this is done like this:

var apple = Titanium.Map.createAnnotation({
	latitude:37.33168900,
	longitude:-122.03073100,
	title:"Steve Jobs",
	subtitle:'Cupertino, CA',
	pincolor:Titanium.Map.ANNOTATION_GREEN,
	animate:true,
	rightButton: 'apple_logo.jpg',
	myid:2 // CUSTOM ATTRIBUTE THAT IS PASSED INTO EVENT OBJECTS
});
 
var atlanta = Titanium.Map.createAnnotation({
		latitude:33.74511,
		longitude:-84.38993,
		title:"Atlanta, GA",
		subtitle:'Atlanta Braves Stadium\nfoo',
		animate:true,
		leftButton:'atlanta.jpg',
		rightButton: Titanium.UI.iPhone.SystemButton.DISCLOSURE,
		myid:3 // CUSTOM ATTRIBUTE THAT IS PASSED INTO EVENT OBJECTS
	});

and the map constructor gets

	annotations:[atlanta,apple]

or later you can add this annotation using

	mapview.addAnnotation(atlanta);

Map events

One thing you need to know is that the events are registered at the map level. So you cannot get a click event on a pin. You will have to get the click event of the mapview ad use the clicksource and the custom property (myId) properties to detect the annotation and what has been clicked (pin, leftbutton, rightbutton, title, subtitle)

	if (evt.source.myid == 3 && evt.clicksource == 'rightButton') {
        // do your stuff
        }

MapRoute

Another thing you can do with a map is to add a route (iOs only for now). Basically you can draw a line on the map specifying the points (gpd point) it needs to pass through.

A route can look like this:

var route = {
	name:"some name",
	points:points,
	color:"red",
	width:2
};

Where points it’s an array of objects containing latitude and longitude coordinates.

screen capture showing a google map on an iphone screen

Example – add a route to a Mapview

Below is an example that adds a route to a mapview using some readymade coordinates. It will generate something similar to the screenshot in the right.

var center = {latitude:42.30,longitude:-71.18,latitudeDelta:0.03, longitudeDelta:0.1};
 
var mapview = Titanium.Map.createView({
	mapType: Titanium.Map.STANDARD_TYPE,
	region: center,
	animate:true,
	regionFit:true
});
 
points = [
	{latitude:42.31,longitude:-71.11},
	{latitude:42.32,longitude:-71.13},
	{latitude:42.31,longitude:-71.22},
	{latitude:42.28,longitude:-71.26}
]
 
// route object
var route = {
	name:"some name",
	points:points,
	color:"#00f",
	width:2
};
 
// add a route
mapview.addRoute(route);

What next?

A good exercise would be maybe to create an application that it’s watching your position while you are driving or walking and display it on a map. All you would have to do is to use the location event and use the returned value to append a new item to the points array.

Anybody wanna try ? :)

Check the Spanish version of this post:
Siete días con Titanium – día 5 – GPS y Mapas

day4

Seven days with Titanium – day 4 – Media – images, movies and sounds

The day 4 comes very late because it was a very busy period so I had no time to continue the tutorials.
Ok, so we should treat in this tutorial the media part of Appcelerator. This includes images – display and capture them with the camera – and how to play movie and sounds.

Display images with Appcelerator

To display an image we use the ImageView. The image view has some simple arguments, like any view in the Titanium framework. I won’t repeat them except for the important one. Obviously the source if the image is the one we are interested in set by the image argument, and accepts local or remote files.

var the_img = Titanium.UI.createImageView({ 
image:"test.jpg"
})

How does Titanium treat the path for local images? The path of the files are simply relative to the Resources folder. So you can use any folder/subfolder under the Resources one to locate the images of your application.

For the remote images a simple url to the image it’s enough.

var the_img = Titanium.UI.createImageView({ 
image:"http://example.com/test.png"
})

Titanium accepts all the formats the targeted OS supports.

How to take pictures using the camera?

The method you have to use is Titanium.Media.showCamera that will display the OS interface for taking photos and expose the 3 possible events (success, cancel, error) to us, so we can decide what to do next.

The function triggered by the success event receives as argument an object containing the media (the image itself) and the width and height of it. Using this data you can create a ImageView and add it to your window for example.

Below is a simple example:

var win = Titanium.UI.currentWindow;
Titanium.Media.showCamera({
 
	success:function(event)
	{
		var image = event.media;
 
		Ti.API.debug('Our type was: '+event.mediaType);
		if(event.mediaType == Ti.Media.MEDIA_TYPE_PHOTO)
		{
			var imageView = Ti.UI.createImageView({width:win.width,height:win.height,image:event.media});
			win.add(imageView);  
		}
		else
		{
			alert("got the wrong type back ="+event.mediaType);
		}
	},
	cancel:function()
	{
               alert('You canceled the action.');
	},
	error:function(error)
	{
		// create alert
		var a = Titanium.UI.createAlertDialog({title:'Camera'});
 
		// set message
		if (error.code == Titanium.Media.NO_CAMERA)
		{
			a.setMessage('Please run this test on device');
		}
		else
		{
			a.setMessage('Unexpected error: ' + error.code);
		}
 
		// show alert
		a.show();
	},
	saveToPhotoGallery:true,
	allowEditing:true,
	mediaTypes:[Ti.Media.MEDIA_TYPE_VIDEO,Ti.Media.MEDIA_TYPE_PHOTO],
});

Like the previous examples this one is found in the Kitchensink provided by Titanium.

Basic sounds with Appcelerator

I will talk only about the basic sounds that are located on the device and can be used as games sounds or as sounds in your application.

The sounds are loaded by the method

var sound = Titanium.Media.createSound({
	url:'cricket.wav'
});

From here you can play, stop, pause, reset, and set the volume of the sound with the methods presented in the documentation page of Titanium.Media.Sound.

Each sound has its events, the most notable being the complete one that triggers when the sound finished to play.

If the sound file is big you should use the preload set to true when you build the sound. If you don’t do this the sound won’t start instantly when you call the play method.

One thing that you need to pay attention to is to release the sound if you don’t need it anymore. For example you play an intro sound only when the user starts the app, then after the sounds completes, you have to release it to free some memory on the device.

var intro_sound = Titanium.Media.createSound({
	url:'cricket.wav',
	preload:true
});
 
intro_sound.addEventListener('complete', function(e){ intro_sound.release(); });
intro_sound.play();
//... more code here

The above code will play the sound and autorelease it when it ends.

Play Videos

Using videos is similar with using sounds. You will have to create a player using the Titanium.Media.createVideoPlayer method.

 
var videoURL = 'http://movies.apple.com/media/us/ipad/2010/tours/apple-ipad-video-us-20100127_r848-9cie.mov';
 
var activeMovie = Titanium.Media.createVideoPlayer({
	url: videoURL,
	width:300,
	height:200,
	top:50,
	left:50,
	backgroundColor:'#0f0'
});
 
view.add(activeMovie);
activeMovie.play();

The url of the videoplayer can be a remote or a local file but you have to take care to be supported by the OS.

On the videoplayer documentation page you will find more about the properties, methods and events supported by this control.

A notable thing is that in the SDK > 3.2 you can embed the videoplayer in any view and play it here without the need of making it fullscreen as in the next screenshot:

embeded_titanium_videoplayer

That’s it for today, see you on Day 5.

Check the Spanish version of this post:
Siete días con Titanium – día 4 – Media – Imágenes, películas y sonidos