Blogs

Alloy Framework in Titanium

May 09, 2013 by anuj khurana

Alloy framework, a new Appcelerator framework built on Node.js and integrated with Titanium Studio. It is based on the model-view-controller architecture with the goal of making Titanium development easier, faster and more scalable.

In this framework UI and App logic seperation is possibe. Alloy utilizes the model-view-controller (MVC) , which separates the application into three different components: 

  • Models: The lowest level of the pattern which is responsible for maintaining data. It provide the business logic, containing the rules, data and state of the application.
  • Views: This is responsible to provide the GUI components to the user.
  • Controllers: Controllers contain the application logic which controls the interactions between View and Model.

 

Create Project

Create project using Titanium Studio

To create a new Alloy project start Titanium studio and follow these steps:

1. From the menu select File > new > Mobile Project. The New Mobile Project wizard appears.

New Mobile Project

2. Select Default Alloy Project from Available Templates box. Choose a Template and click Next button.

3. Complete all of the fields and click Finish button.

New Project Details

 

Directory Structure

When you open the project you will find the directories as displayed in the image below.

Directory Structure Image

View

We declare the structure of GUI in a view. The file below define a window and a label in window. We can define here Id, Class, Platform Specific, Inline Events etc.

Index.xml

<Alloy>
	<Window class="container">
		<Label id="label" onClick="doClick" platform="android">Hello, Android User</Label>
		<Label id="label" onClick="doClick" platform="ios">Hello, iPhone User</Label>
	</Window>
</Alloy>


 

Style

The style file styles the components in the view file. For example the style below defines the label top to 50 and Label color is red.

Note: You can create a global style file called app.tss, which applies all styles defined inside to all views.

Index.tss

".container": {
	backgroundColor:"white"
},
"#Label": {
	top: "50dp",
        width: Ti.UI.SIZE,
	height: Ti.UI.SIZE,
	color: "red"
} 

 

Controller

Controllers contain the application logic which controls the interactions between View and Model. The file below define a doClick function which alerts the label value.

 

function doClick(e) {  
    alert($.label.text);
}

$.index.open();

Difference

The image below differentiate the classic Titanium App structure and Alloy App Structure.

Titanium App Vs Alloy App

With alloy developers can build apps not only faster, but a higher quality and reusabe components that can be used in every project.

Hope it Helps !

Anuj Khurana

anuj.khurana@oodlestechnologies.com

http://oodlestechnologies.com/

Scan Barcodes through camera in iOS and Android mobile applications built using Titanium

January 21, 2013 by anujv

This blog demonstrates the integration of Barcode Reader into your iOS/Android mobile app in Titanium using Acktie Mobile Barcode Reader Module.

You may download the Module for iOS / Android from the link below :

http://www.acktie.com/our-modules/barcode-reader-module/

 

  • Create a new project in titanium.

Add the downloaded modules for iOS and Android in your tiapp.xml file.

  • Now, replace your "app.js" code with the code written below :
  • Create a window and include the "barcode reader module" in the window.

 

// this sets the background color of the master UIView (when there are no windows/tab groups on it)
Titanium.UI.setBackgroundColor('#000');

// create tab group
var tabGroup = Titanium.UI.createTabGroup();
//
// create base UI tab and root window
//
var win1 = Ti.UI.createWindow({
	backgroundColor : 'white',
	title: "Scan Barcode",
});
var tab1 = Titanium.UI.createTab({
	icon : 'KS_nav_views.png',
	title : 'Tab 1',
	window : win1
});

var barcodereader = undefined;
var barcodeCodeWindow = undefined;
var barcodeCodeView = undefined;

// Depending on the platform, include the appropriate barcode module
if (Ti.Platform.osname === 'iphone' || Ti.Platform.osname === 'ipad') {
	barcodereader = require('com.acktie.mobile.ios.barcode');
} else if (Ti.Platform.osname === 'android') {
	barcodereader = require('com.acktie.mobile.android.barcode');
}

 

  • Create an Array and include all the Barcode types available.
// All supported Barcode types
var ALL = [
    "EAN2",
    "EAN5",
    "EAN8",
    "UPCE",
    "ISBN10",
    "UPCA",
    "EAN13",
    "ISBN13",
    "COMPOSITE",
    "I25",
    "DATABAR",
    "DATABAR_EXP",
    "CODE39",
    "PDF417",
    "CODE93",
    "CODE128",];


  • Function that includes the Barcode reader behaviour, for Android :
   
/*
 * Function that mimics the iPhone Barcode Code reader behavior.
 */
function scanBarcodeFromCamera(options) {
	barcodeCodeWindow = Titanium.UI.createWindow({
		backgroundColor : 'black',
		width : '100%',
		height : '100%',
	});
	barcodeCodeView = barcodereader.createBarcodeView(options);

	var closeButton = Titanium.UI.createButton({
		title : "close",
		bottom : 0,
		left : 0
	});
	var lightToggle = Ti.UI.createSwitch({
		value : false,
		bottom : 0,
		right : 0
	});

	closeButton.addEventListener('click', function() {
		barcodeCodeView.stop();
		barcodeCodeWindow.close();
	});

	lightToggle.addEventListener('change', function() {
		barcodeCodeView.toggleLight();
	})

	barcodeCodeWindow.add(barcodeCodeView);
	barcodeCodeWindow.add(closeButton);

	if (options.userControlLight != undefined && options.userControlLight) {
		barcodeCodeWindow.add(lightToggle);
	}

	// NOTE: Do not make the window Modal.  It screws stuff up.  Not sure why
	barcodeCodeWindow.open();
}



  • Now, create a button on click of which barcode has to be read.
/**
 * Read Barcode code from the Camera feed.  Once the Barcode code is read it will
 * stop scanning.
 */
var barcodeFromCameraButton = Titanium.UI.createButton({
	title : 'Barcode from Camera (All)',
	height : 40,
	width : '100%',
	top : 60
});
barcodeFromCameraButton.addEventListener('click', function() {
	var options = {
		// ** Android Barcode Reader properties (ignored by iOS)
		backgroundColor : 'black',
		width : '100%',
		height : '90%',
		top : 0,
		left : 0,
		// **

		// ** Used by both iOS and Android
		overlay : {
			color : "blue",
			layout : "center",
			alpha : .75
		},
		barcodes:ALL,
		success : success,
		cancel : cancel,
		error : error,
	};

	if (Ti.Platform.name == "android") {
		scanBarcodeFromCamera(options);
	} else {
		barcodereader.scanBarcodeFromCamera(options);
	}
});

win1.add(barcodeFromCameraButton);

function success(data) {
	if(data != undefined && data.data != undefined) {
		Titanium.Media.vibrate();
		alert('data: ' + data.data + ' type: ' + data.type);
	}
};

function cancel() {
	alert("Cancelled");
};

function error() {
	alert("error");
};

 

  • Now, after all the code written your "app.js" will look like the one below:

 

   
Titanium.UI.setBackgroundColor('#000');

var tabGroup = Titanium.UI.createTabGroup();

var win1 = Ti.UI.createWindow({
	backgroundColor : 'white',
	title: "Scan Barcode",
});
var tab1 = Titanium.UI.createTab({
	icon : 'KS_nav_views.png',
	title : 'Tab 1',
	window : win1
});

var barcodereader = undefined;
var barcodeCodeWindow = undefined;
var barcodeCodeView = undefined;

if (Ti.Platform.osname === 'iphone' || Ti.Platform.osname === 'ipad') {
	barcodereader = require('com.acktie.mobile.ios.barcode');
} else if (Ti.Platform.osname === 'android') {
	barcodereader = require('com.acktie.mobile.android.barcode');
}

var ALL = [
    "EAN2",
    "EAN5",
    "EAN8",
    "UPCE",
    "ISBN10",
    "UPCA",
    "EAN13",
    "ISBN13",
    "COMPOSITE",
    "I25",
    "DATABAR",
    "DATABAR_EXP",
    "CODE39",
    "PDF417",
    "CODE93",
    "CODE128",];

var barcodeFromCameraButton = Titanium.UI.createButton({
	title : 'Barcode from Camera (All)',
	height : 40,
	width : '100%',
	top : 60
});
barcodeFromCameraButton.addEventListener('click', function() {
	var options = {
		backgroundColor : 'black',
		width : '100%',
		height : '90%',
		top : 0,
		left : 0,
		overlay : {
			color : "blue",
			layout : "center",
			alpha : .75
		},
		barcodes:ALL,
		success : success,
		cancel : cancel,
		error : error,
	};

	if (Ti.Platform.name == "android") {
		scanBarcodeFromCamera(options);
	} else {
		barcodereader.scanBarcodeFromCamera(options);
	}
});

win1.add(barcodeFromCameraButton);

function success(data) {
	if(data != undefined && data.data != undefined) {
		Titanium.Media.vibrate();
		alert('data: ' + data.data + ' type: ' + data.type);
	}
};

function cancel() {
	alert("Cancelled");
};

function error() {
	alert("error");
};

function scanBarcodeFromCamera(options) {
	barcodeCodeWindow = Titanium.UI.createWindow({
		backgroundColor : 'black',
		width : '100%',
		height : '100%',
	});
	barcodeCodeView = barcodereader.createBarcodeView(options);

	var closeButton = Titanium.UI.createButton({
		title : "close",
		bottom : 0,
		left : 0
	});
	var lightToggle = Ti.UI.createSwitch({
		value : false,
		bottom : 0,
		right : 0
	});

	closeButton.addEventListener('click', function() {
		barcodeCodeView.stop();
		barcodeCodeWindow.close();
	});

	lightToggle.addEventListener('change', function() {
		barcodeCodeView.toggleLight();
	})

	barcodeCodeWindow.add(barcodeCodeView);
	barcodeCodeWindow.add(closeButton);

	if (options.userControlLight != undefined && options.userControlLight) {
		barcodeCodeWindow.add(lightToggle);
	}

	barcodeCodeWindow.open();
}

if (Ti.Platform.osname == 'android') {
	var activity = Ti.Android.currentActivity;
	activity.addEventListener('pause', function(e) {
		Ti.API.info('Inside pause');
		if (barcodeCodeView != undefined) {
			barcodeCodeView.stop();
		}

		if (barcodeCodeWindow != undefined) {
			barcodeCodeWindow.close();
		}
	});
}

tabGroup.addTab(tab1);

tabGroup.open();

  • iOS and Android screenshots are provided below :

  

 

  

 

Hope this helps..

Anuj Vashistha

anuj.vashistha@oodlestechnologies.com

http:/oodlestechnologies.com/

Display advertisements on iOS and Android Apps using Google Admob in Titanium

January 18, 2013 by anujv

The blog below exemplifies the effectual way to integrate Admob Ads within your titanium mobile app in iOS and Android.

We'll discuss the method with the source code below. First you need to download the Admob module.

You can download it through the link :

https://github.com/appcelerator/titanium_modules/blob/master/admob/mobile/android/dist/ti.admob-android-2.1.0.zip (for ANROID)

http://github.com/appcelerator/titanium_modules/blob/master/admob/mobile/ios/ti.admob-iphone-1.4.0.zip (for iOS)

Click on View Raw to download the zip files for both ios and android.

Follow the steps below to Integrate the admob module with your titanium app and show ads in your app.

(1) Integrate Admob Module in titanium studio.

After successfully downloading the zip file, extract it. 

You will find "ti.admob" inside 'iPhone' and 'android' folders.

Navigate to your ~"/Library/Application Support/Titanium/modules" folder, there you will find             two folders "android" and "iPhone". 

Copy the downloaded "ti.admob" for android in "android" folder and another one in "iPhone"    folder.

Now open titanium studio, create a new "titanium project".

Open project's tiapp.xml file.

Open overview tab, Add the "ti.admob" module by clicking on the '+' symbol at the top right corner.

Open tiapp.xml tab.

 Now replace the code :

 

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

 

with

 

<android xmlns:android="http://schemas.android.com/apk/res/android">
       <manifest>
            <supports-screens android:anyDensity="true"
                android:largeScreens="true" android:normalScreens="true" android:smallScreens="true"/>
        </manifest>
        <uses-permission android:name="android.permission.INTERNET"/>
        <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
        <tool-api-level>14</tool-api-level>
        </android>

# Here you are done with successful installation and integration of admob module in titanium.

 (2) Using the module to display ads on device.

 Since, we've different modules for Android and iOS applications, their api's are also little variant. We''ll create different ad views for "Android" and "iOS".

 Open "app.js" file in your project.

  • Include Admob module in the main window

 

	var adMob = require ('ti.admob');

 

  • Create Ad View for iOS :

 

	var ad = adMob.createView({
	width : '320dp',
	height : '50dp',
	top : '-50dp',
	publisherId : " ", // You can get your own at http://www.admob.com/
	testing : false
	});
	win1.add(ad);

  

 

  • Add Event Listener to show ad in iOS when received :

 

	ad.addEventListener('didReceiveAd', function() {
	ad.animate({ 
        top : 0, 
        duration : 500 }); 
    });

    

 

  • Create Ad View for Android :

 

	var ad = adMob.createView({
	width : '100%',
	height : '50dp',
	top : '-50dp',
	backgroundColor : '#000',
	focusable : true,
	publisherId : " ",// You can get your own at http: //www.admob.com/
	testing : false
	});
	win1.add(ad);

 

  • Add Event Listener to show ad in Android when received :

 

	 ad.addEventListener(adMob.AD_RECEIVED, function() {
         ad.animate({
         top : 0,
	  duration : 500 }); 
     });

  

 

  • Ultimately, your "app.js" would look relatively like :

 

	// this sets the background color of the master UIView (when there are no windows/tab groups on it)

	Titanium.UI.setBackgroundColor('#000');

	 

	// create tab group

	var tabGroup = Titanium.UI.createTabGroup();

	 

	// include ti.admob module

	var adMob = require('ti.admob');

	var osName = Ti.Platform.osname;

	// create base UI tab and root window

	var win1 = Titanium.UI.createWindow({
	title : 'Tab 1',
	backgroundColor : '#fff'
	});

	var tab1 = Titanium.UI.createTab({
	icon : 'KS_nav_views.png',
	title : 'Tab 1',
	window : win1
	});
	 

	var label1 = Titanium.UI.createLabel({
	color : '#999',
	text : 'I am Window 1',
	font : {
	fontSize : 20,
	fontFamily : 'Helvetica Neue'
	},
	textAlign : 'center',
	width : 'auto'
	});
	 
	win1.add(label1);
	 

	if(osName != 'android')
	{
	var ad = adMob.createView({
	width : '320dp',
	height : '50dp',
	top : '-50dp',
	publisherId : " ", // You can get your own at http: //www.admob.com/
	testing : false
	});
	win1.add(ad);
	ad.addEventListener('didReceiveAd', function() {
	            ad.animate({
	                top : 0,
	                duration : 500
	            });
	        });
	}
	else{
	var ad = adMob.createView({
	width : '100%',
	height : '50dp',
	top : '-50dp',
	backgroundColor : '#000',
	focusable : true,
	publisherId : " ",// You can get your own at http: //www.admob.com/
	testing : false
	});
	win1.add(ad);

	ad.addEventListener(adMob.AD_RECEIVED, function() {
	            ad.animate({
	                top : 0,
	                duration : 500
	            });
	        });
	}
	 
	 
	//
	//  add tabs
	//
	tabGroup.addTab(tab1);
	 
	// open tab group
	tabGroup.open();

  •  Screen shots for iPhone and Android are shown below :

      

 

Hope it helps..

Anuj Vashistha

anuj.vashistha@oodlestechnologies.com

http://oodlestechnologies.com/

Tracking Install Referrer or Campaign Referrer for Android App in Titanium

December 19, 2012 by ARPIT SHARMA

In this blog you will find how to create a Titanium Android Module for tracking Install Referral.

Install Referral is use to track the installation source of android application. First of all we have to create a android module, please click here for the steps and install ndk from here.

After creating the android module, you have to follow the following steps :

  • Import android module into Eclipse( File > Import > Existing Projects into Workspace).
  • Open build.properties file and add android ndk path into it, example : android.ndk=/Users/user_name/android-ndk-r8b
  • Create a new class (ReferrerCatcher.java) in src > com.yourpackage folder.
  • Now, extends BroadcastReceiver in ReferrerCatcher class and implement onReceive function into it.

 

package com.oodles.referral;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;

public class ReferrerCatcher extends BroadcastReceiver{

	@Override
	public void onReceive(Context context, Intent intent) {
		// TODO Auto-generated method stub
		
	}

}

  • You will get the install url through Intent object and store the require parameter using SharedPreferences.

 

package com.oodles.referral;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.util.Log;

public class ReferrerCatcher extends BroadcastReceiver {

	final String INSTALL_PREFERENCE = "installPrefrences";
	final String REFERRAL_URL = "InstallReferral";

	@Override
	public void onReceive(Context context, Intent intent) {
		// TODO Auto-generated method stub
		Log.i("installReferralTracker", "installReferralTracker Broadcast Receiver info");
		
		//Getting install url from intent object 
		String uri = intent.toURI();
		
		if (uri != null && uri.length() > 0) {
			int index = uri.indexOf("utm_source=");
			if (index > -1) {
				
				//Getting require parameters from url
				uri = uri.substring(index, uri.length() - 4);
				Log.i("installReferralTracker", "Referral URI: " + uri);
				
				//Store paramaters using SharedPreferences
				SharedPreferences settings = context.getSharedPreferences(INSTALL_PREFERENCE, 0);
				SharedPreferences.Editor editor = settings.edit();
				editor.putString(REFERRAL_URL, uri);
				editor.commit();

				Log.i("installReferralTracker", "Cached Referral URI: " + uri);
			} else
				Log.i("installReferralTracker", "No Referral URL.");
		}
		Log.i("installReferralTracker", "End");
	}
}
  • Now open Your_Module_NameModule.java and declare SharedPreferences object and other variables in class, example

 

public class ReferralModule extends KrollModule {
	
final String REFERRAL_URL = "InstallReferral";
	
static SharedPreferences settings;
	
// Standard Debugging variables
private static final String LCAT = "ReferralModule";

  • Next step is to defined the SharedPreferences object in onAppCreate method.

 

public static void onAppCreate(TiApplication app) {
		Log.d(LCAT, "inside onAppCreate");
		// put module init code that needs to run when the application is created
		settings = app.getSharedPreferences("installPrefrences", 0);
	}
  • Create a method get_utm_source() which returns the store parameter string.

 

public String get_utm_source() {
		Log.d(LCAT, "get_utm_source called");
		
		String referralURL = settings.getString(REFERRAL_URL, null);
		
		if (referralURL != null && !referralURL.equals("")) {
			return referralURL;
		} else {
			return "referralURL is null";
		}
	}
  • Right click on build.xml and Run As "Ant Build", after build sucessfully go to the module directory then "dist" foldar now extart the zip file and place the module into titanium module foldar and add the module in project.
  • In Titanium, you can use the module by calling get_utm_source() function but before this you have to add couple of lines in tiapp.xml

 

<receiver android:exported="true" android:name="your.package.ReferrerCatcher">         
      <intent-filter>
        <action android:name="com.android.vending.INSTALL_REFERRER" />
      </intent-filter>
</receiver>

 

var win = Ti.UI.createWindow({
	backgroundColor : "#fff"
});
//Getting the module object
var referral = require('com.oodles.referral');

//Call the function get_utm_source()
var utm_source = referral.get_utm_source();

alert(utm_source);

win.open();

This is how you can track the  Install Referrer or Campaign Referrer for Android App in Titanium, i hope this will help you.

 

Arpit Sharma
arpit.sharma@oodlestechnologies.com

http://oodlestechnologies.com/

Implementing Pull to refresh (like in Facebook mobile app) for ANDROID using Titanium

August 08, 2012 by ankush gulati

Pull to Refresh header (like in Facebook mobile app and famous Twitter client Tweetie) is an innovative and pleasant way of Refreshing the contents. There are many alternatives to have this kind of interface. Like for iOS, one is precisely described HERE

However, above procedure works for iOS only. So, here we discuss an alternative for ANDROID. We'll be using a scrollview to implement this.


1.) First of all we need to create a scrollView as follows:

var scrollView = Ti.UI.createScrollView({
			contentHeight : 'auto',
			layout : 'vertical',
			showVerticalScrollIndicator: true
			});

Above code creates a default scrollView. All the items which are to refreshed like table, labels, fields etc. should be placed inside this scrollView.


2.) Now, we need to create a view (say tableHeader) which sits on the top of the scrollview. This tableHeader will contain an Arrow icon which rotates when user pulls the scrollview to a certain point, a Status Label, indicating the text either PULL TO REFRESH or RELEASE TO RELOAD accordingly.

var tableHeader = Ti.UI.createView({
			width: '100%',
			height: '60dp',
		});

		var arrow = Ti.UI.createView({
			backgroundImage : "/images/redArrow.png",       //your custom image path here.
			width : '23dp',
			height : '40dp',
			bottom : '10dp',
			left : '25dp'
		});
		tableHeader.add(arrow);
		
		var statusLabel = Ti.UI.createLabel({
			text : 'Pull To Refresh',
			textAlign : Ti.UI.TEXT_ALIGNMENT_CENTER,
			bottom : '30dp',
			height : "auto",
			font : {
				fontSize : '11sp',
				fontWeight : "bold"
			}
		});
		tableHeader.add(statusLabel);

		scrollView.add(tableHeader);	

3.) The next step is to initialize the position of tableHeader i.e. it needs to be Hidden when the page loads initially and should only be visible when scrollview is Pulled Down. So, we use the scrollView scrollTo(x,y) property as follows:

var init = setInterval(function(e){
			if (offset==60) {
				clearInterval(init);
			}
			scrollView.scrollTo(0,60);
		},100);


4.) Now, we need to create the animation affects (rotating arrows). The basic idea is to get the offset of Y coordinate to detect how far the scrollview is pulled.

                var offset = 0;
		scrollView.addEventListener('scroll', function(e) {
			if (e.y!=null) {
				offset = e.y;
			}
				if (offset <= 5) {
				var t = Ti.UI.create2DMatrix();
				t = t.rotate(-180);
				arrow.animate({
					transform : t,
					duration : 180
				});
				statusLabel.text = 'Release To Reload';
			}
			else if (offset > 5 && offset < 60) {				
				var t = Ti.UI.create2DMatrix();
				arrow.animate({
					transform : t,
					duration : 180
				});
				statusLabel.text = 'Pull To Refresh';
			}
			
		});

As it's clear from the above code snippet, if the offset reaches the value we require, then we start the arrow rotation and change the statusLabel. So, now we have to implement when to reload and when to again HIDE the tableHeader.


5.) Now, the last step is to decide whether to REFRESH the page or just simply scroll back to original positions as to HIDE the tableHeader, after the user has stopped scrolling.

	scrollView.addEventListener('touchend', function() {
			if (offset<=5) {	
				Ti.App.fireEvent('app:refreshContents');    //Your custom event to REFRESH fired here
				scrollView.scrollTo(0,60);
						
			} 
			else if (offset<60)
			 {
				scrollView.scrollTo(0,60);
			} 
		});

The code Ti.App.fireEvent('app:refreshContents') should be replaced by the code which should refresh the scrollView's contents. Use this approach and you are ready to have Pull to refresh.


Ankush Gulati
ankush.gulati@oodlestechnologies.com
http://oodlestechnologies.com/

Authenticating users from LinkedIn or Twitter in iOS and Android using Titanium

July 30, 2012 by ARPIT SHARMA

Here we'll discuss how to authenticate users on your app from linkedIn or Twitter.

First of all download libraries Oauth.js and sha1.js  and put them into lib folder.

We have to follow three steps for authentication.

1. Request token

2. Show the authentication page to authorize the app. and get the pin.

3. Get the access token.

Create oauth_client.js file in which we'll execute above three.

  • Include Oauth.js and sha1.js in oauth_client.js.
Ti.include('lib/sha1.js');
Ti.include('lib/oauth.js');

 

  • Create a function name oauth_client and defined the app keys, rest API's and variables in it. 
var oauth_client = function() {

	// You will get this key and secret when you create the application in LinkedIn or twitter.
	var CONSUMER_KEY = 'xxxxxxxxxx';
	var CONSUMER_SECRET = 'xxxxxxxxxxxxxxxxxxxxxxx';

	// these are the linkedIn REST API
	var REQUEST_TOKEN_URL = 'https://api.linkedin.com/uas/oauth/requestToken';
	var AUTHORIZE_URL = 'https://api.linkedin.com/uas/oauth/authorize';
	var ACCESS_TOKEN_URL = 'https://api.linkedin.com/uas/oauth/accessToken?';
        
       // these are the twitter REST API
	/*var REQUEST_TOKEN_URL = 'https://api.twitter.com/oauth/request_token';
	var AUTHORIZE_URL = 'https://api.twitter.com/oauth/authorize';
	var ACCESS_TOKEN_URL = 'https://api.twitter.com/oauth/access_token';*/
        
       // the accessor is used when communicating with the OAuth libraries to sign the messages
	var accessor = {
		consumerSecret : CONSUMER_SECRET,
		tokenSecret : ''
	};

	var pin = null;
	var oauth_token = null;
	var oauth_token_secret = null;

	//@method get_oauth_token
	this.get_oauth_token = function() {
		return oauth_token;
	};
	
	 //@method get_oauth_token_secret
	this.get_oauth_token_secret = function() {
		return oauth_token_secret;
	};

	 //@method get_pin
	this.get_pin = function() {
		return pin;
	};

	//@method get_pin
	this.set_pin = function(html) {

		// for Twitter
		//var regExp = '(.*?)';

		// for linkedIn
		var regExp = /<div class="access-code">(.*?)<\/div>/;

		var result = RegExp(regExp).exec(html);
		if (result == null || result.length < 2) {
			pin = null;
			Ti.API.debug('Result : ' + result);
			return null;
		}
		pin = result[1];
		return pin;
	}
}


 

  • Now added request_token the 1st step for authentication in oauth_client function.
        /**
	 * 1st step of oAuth.
	 * @method request_token
	 */
	this.request_token = function(complete) {
		var message = {
			action : REQUEST_TOKEN_URL,
			method : 'POST',
			parameters : []
		};

		message.parameters.push(['oauth_consumer_key', CONSUMER_KEY]);
		message.parameters.push(['oauth_signature_method', 'HMAC-SHA1']);

		OAuth.setTimestampAndNonce(message);
		OAuth.SignatureMethod.sign(message, accessor);

		var client = Ti.Network.createHTTPClient();
		client.open('POST', REQUEST_TOKEN_URL, true);
		client.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded;');
		client.setRequestHeader("Authorization", OAuth.getAuthorizationHeader("", message.parameters));

		client.onload = function() {
			Ti.API.debug('[load]' + this.status);
			var responseParams = OAuth.getParameterMap(client.responseText);

			oauth_token = responseParams['oauth_token'];
			oauth_token_secret = responseParams['oauth_token_secret'];

			if (complete != 'undefined') {
				complete();
			}
		}
		client.send(null);
	};

 

  • Added get_authorize_url_with_token the 2nd step for authentication in oauth_client function.
       /**
	 * 2nd step of oAuth.
	 * @method get_authorize_url_with_token
	 */
        this.get_authorize_url_with_token = function() {
		return AUTHORIZE_URL + '?oauth_token=' + oauth_token;
	};

 

  • Added access_token the 3rd step for authentication in oauth_client function.
        /**
	 * 3rd step of oAuth.
	 * @method access_token
	 */
	this.access_token = function(complete) {
		accessor.tokenSecret = oauth_token_secret;

		var message = {
			action : ACCESS_TOKEN_URL,
			method : 'POST',
			parameters : []
		};
		message.parameters.push(['oauth_consumer_key', CONSUMER_KEY]);
		message.parameters.push(['oauth_token', oauth_token]);
		message.parameters.push(['oauth_signature_method', 'HMAC-SHA1']);
		message.parameters.push(['oauth_verifier', pin]);

		OAuth.setTimestampAndNonce(message);
		OAuth.SignatureMethod.sign(message, accessor);

		var client = Ti.Network.createHTTPClient();

		client.open('POST', ACCESS_TOKEN_URL, true);
		client.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded;');
		client.setRequestHeader("Authorization", OAuth.getAuthorizationHeader("", message.parameters));

		client.onload = function() {
			var responseParams = OAuth.getParameterMap(client.responseText);
			oauth_token = responseParams['oauth_token'];
			oauth_token_secret = responseParams['oauth_token_secret'];
			complete.call();
		}
		client.send(null);
	};

 

In app.js file we have to added the following code.

Ti.include('oauth_client.js');

var popup_window = Ti.UI.createWindow({
	backgroundColor : "#fff"
});

//Create the client instance.
var client = new oauth_client();

//Create the label that shows "loading" message so user knows that something is happening.
var loadingLabel = Ti.UI.createLabel({
	text : 'Loading... Please wait.',
});
popup_window.add(loadingLabel);

/**
 * This is the 2nd step of oAuth. It will show the authentication page for you to enter user name and password to authorize the app.
 */
var show_on_webview = function(url, complete) {
	var view = Ti.UI.createView({
		width : "100%",
		height : "100%",
		border : 10,
		backgroundColor : 'white',
		borderColor : '#aaa',
		borderWidth : 5,
	});
	var closeLabel = Ti.UI.createLabel({
		textAlign : 'right',
		font : {
			fontWeight : 'bold',
			fontSize : '8sp'
		},
		text : '(X)',
		top : 10,
		right : 12,
		height : 35
	});
	var webView = Ti.UI.createWebView({
		url : url,
		top : "55dp",
		width : "100%",
		height : "100%",
	});
	view.add(webView);
	webView.addEventListener('beforeload', function(e) {
		if (Ti.Platform.osname == "android")
			view.visible = false;
	});
	webView.addEventListener('load', function(e) {
		var html = e.source.html;
		client.set_pin(html);
		if ((complete != 'undefined') && (client.get_pin() != null)) {
			complete();
		}
		if (Ti.Platform.osname == "android")
			view.visible = false;
	});
	closeLabel.addEventListener('click', function() {
		popup_window.close();
	});
	view.add(closeLabel);
	popup_window.add(view);
	return;
};

/**
 * Save the token, secret and pin in file.
 */
var save_token_and_secret = function() {
	Ti.App.Properties.setString("oauth_token", client.get_oauth_token());
	Ti.App.Properties.setString("oauth_token_secret", client.get_oauth_token_secret());
	Ti.App.Properties.setString("pin", client.get_pin());
	alert("Authentication Complete");
}
/**
 * Save the token, secret and pin in file.
 */
var get_access_token = function() {
	client.access_token(function() {
		save_token_and_secret();
	});
}
var login = function() {
	client.request_token(function() {
		show_on_webview(client.get_authorize_url_with_token(), get_access_token);
	});
}
login();
popup_window.open();

 

Arpit Sharma
arpit.sharma@oodlestechnologies.com

http://oodlestechnologies.com/

Push Notifications using Google Cloud Messaging (GCM) in Android (Part 1)

July 25, 2012 by Varun Sharma

Android has replaced C2DM (Cloud to Device Messaging) service with GCM (Google Cloud Messaging).
I have used Google Cloud Messaging (GCM) in one of my projects to send notifications to Android device. I decided to write this blog so that others can use GCM (before C2DM)  in Android, with ease in their projects.

I have used Both Server Side (Grails) & Client Side (Titanium) to send notifications to the android device. So, I will be explaining you both one by one. But before that you need to add ADT plugin in to your Grails framework.

 

Add ADT Plugin in Grails

1. Start Grails, then select Help > Install New Software...

2. Click Add, in the top-right corner.

3. In the Add Repository dialog that appears, enter "ADT Plugin" for the Name and the following URL for the Location: https://dl-ssl.google.com/android/eclipse/

4. Click OK

Note: If you have trouble acquiring the plugin, try using "http" in the Location URL, instead of "https" (https is preferred for security reasons).

5. In the Available Software dialog, select the checkbox next to Developer Tools and click Next.

6. In the next window, you'll see a list of the tools to be downloaded. Click Next.

7. Read and accept the license agreements, then click Finish.

Note: If you get a security warning saying that the authenticity or validity of the software can't be established, click OK

8. When the installation completes, restart Grails.


Note: You need Android SDK

1. First you need to download the Android SDK

2. Your download package is a .tgz. Unpack it to a safe location on your machine. By default, the SDK files are unpacked into a directory named android-sdk-linux_x86.

 

Configuring ADT Plugin

After you've installed ADT and restarted Grails, you must specify the location of your Android SDK directory:

1. Select Window > Preferences... to open the Preferences panel (on Mac OS X, select Eclipse > Preferences)

2. Select Android from the left panel.
You may see a dialog asking whether you want to send usage statistics to Google. If so, make your choice and click Proceed.

3. For the SDK Location in the main panel, click Browse... and locate your downloaded Android SDK directory (such as android-sdk-linux_x86).

4. Click Apply,then OK.

If you haven't encountered any errors, you're done setting up ADT.


Now As you have sucessfully added the ADT plugin & Android SDK, you are all set up to go for Server Side & Client Side development.

 

How to Register Android Device for GCM & How to send notifications to device from server will be discussed in Next Part.

Push Notifications using Google Cloud Messaging (GCM) in Android (Part 2) 

 

Hope it helps !

Varun Sharma
varun.sharma@oodlestechnologies.com

http://oodlestechnologies.com/

Using MVC and optimized code structure in Titanium Appcelerator Projects

July 06, 2012 by anuj khurana

In this blog you will find how we can optimize the code structure for titanium projects . Here I try to use common JS format as much as possible to structure the app. I specially created some UI constants for the theme so we keep it DRY.

Below I am outlining few components in code structure using a demoProject for explaination . You can also download the demoProject source from github location mentioned below.

app.js

var platform= Ti.Platform.osname;
var win = require('/ui/windows/' + platform + 'ui/firstWindow').createFirstWindow()
win.open();

I created three directories ipadui/iphoneui/androidui where I have declared the UI stuff for the screens.

In this demoProject I include underscore.js utility-belt library for JavaScript that provides a lot of the functional programming support.

Here is the link if you want to include this file in your project:

http://documentcloud.github.com/underscore/#

Directory Structure

When you open the project you will find the directories as displayed in the image below. Here I created some directories manually for controller,UI and library.

Directory Structure

  • Controllers contains all operations performed on button clicks and other event listeners. Controllers are common for all platforms (android/iOS).
  • Lib contains all library files which is useful in project for example underscore.js, events.js etc.
  • UI contains all screens UI designs for all platforms.

UI constants for the theme

In UI directory I have created a ui.js and declare functions for UI constans. These functions are common for all the UI screens. It helps us to keep our code DRY.

ui.js

var _ = require("/lib/underscore");
var applyDefaults = function(params, defaults) {
	params = params || {};
	_.defaults(params, defaults);
};

Here I include underscore.js and create a function “applyDefaults” for overriding the default value if user define any value.

Create window

Here I define the window default properties like layout, backgroundImage which is common for all screens. There is no need to define them in all screens. We can keep our code DRY by defining the default params in ui.js.

ui.js

exports.createWindow = function(params) {
	params = params || {};
	var defaults = {
		layout : 'vertical',
		title:'New Window',
    	backgroundImage:'/images/back.png',
   		barColor : '#121212',
	};
	applyDefaults(params, defaults);
	return Ti.UI.createWindow(params);
};

In firstWindow.js we need to define only the title. All the other property will comes from ui.js. The title value will be override.

We need to include ui.js in firstWindow.js

firstWindow.js

var ui = require('/ui/ui');
var win = ui.createWindow({
	title : "Welcome",
	});

 

Create button

Here I define the button default properties like backgroundImage, color, height, width which is common for all screens. There is no need to define them in all screens.

ui.js

exports.createButton = function(params) {
	params = params || {};

	var defaults = {
		title : 'Default button',
		backgroundImage : '/images/button.png',
		color : '#dbdbdb',
		height : '37dp',
		width : '80%',
		top : '10dp',
	};
	if(platform == "ipad") {
		defaults.width = 300;

	}
	applyDefaults(params, defaults);
	return Ti.UI.createButton(params);
}; 

 

In firstWindow.js we need to define only the title and top. All the other property will comes from ui.js. The title and top value will be override.

firstWindow.js

var submit = ui.createButton({
		title : "Submit",
		top : 20,
	});

 

Create Text Field

Here I define the textField default properties like height, width which is common for all screens. There is no need to define them in all screens.

ui.js

exports.createTextField = function(params) {
	params = params || {};

	var defaults = {
		height : '37dp',
		top : '10dp',
		width : '80%',
		keyboardType : Ti.UI.KEYBOARD_DEFAULT,
		returnKeyType : Ti.UI.RETURNKEY_DEFAULT,
		borderStyle : Ti.UI.INPUT_BORDERSTYLE_ROUNDED
	};
	if(platform == "ipad") {
		defaults.width = 300;

	}
	applyDefaults(params, defaults);
	return Ti.UI.createTextField(params);
};

 

In firstWindow.js we need to define only top. All the other property will comes from ui.js. The top value will be override.

firstWindow.js

var fieldUserName = ui.createTextField({
		top : 3,
	});
var fieldEmail = ui.createTextField({
		top : 3,
	});

 

Create controller for firstWindow

In ui directory I define only UI stuff in separate directory for iphone, ipad and android. No there is need to define common controller for all three platforms.

Including the /controllers/firstWindow.js

ui/windows/firstwindow.js

Ti.include('/controllers/firstWindow.js');
var controller = createController(win);

 

In /controllers/firstWindow.js we define the EventListener for submit button. This is accessable on all platforms.

/controllers/firstWindow.js

function createController(win) {
	var platform= Ti.Platform.osname;
	win.submit.addEventListener('click', function() {
		if(win.fieldUserName.value == "" || win.fieldEmail.value == "") {
			alert('please fill both fields');

		} else {
			var secondWindow = require('/ui/windows/' + platform + 'ui/secondWindow').createSecondWindow(win.fieldUserName.value);
			secondWindow.open();
		}
	});
};

 

Using this code structure we can simplify our project code structure.

To download this Demo Project Please click on the link below:

https://github.com/anuj6117/demoProject.git

Hope it Helps !

Anuj Khurana

anuj.khurana@oodlestechnologies.com

http://oodlestechnologies.com/

Performance optimizations for Android apps built using Titanium

July 03, 2012 by anuj khurana

DDMS

While running your Android app, the app suddenly freeze and there’s a dialog box asking you to FORCE CLOSE the app. This is what happen when your Android app has RUNTIME ERROR!

To solve this issue there’s a tool available - DDMS

Force Close Image

 

 

Go to the Android SDK folder open Tools and select DDMS

 

As part of the compile process the deployment in the emulator, the console statements in titanium are quite lengthy and in details. This is very hard to find the debug statements. DDMS provides the solution for this.

 

In the left panel there is an emulator process. All the application which is installed in emulator is in left panel. You can choose which device you’d like to debug. In my case I have my emulator and the com.test is the application. The LogCat is the place you could see warnings and errors messages from the device.

 

Using DDMS

The following sections describe how to use DDMS and the various tabs and panes that are part of the DDMS GUI.

 

Viewing heap usage for a process

DDMS allows you to view how much heap memory a process is using. This information is useful in tracking heap usage at a certain point of time during the execution of your application.

To view heap usage for a process:

  • In the Devices tab, select the process that you want to see the heap information for.
  • Click the Update Heap button to enable heap information for the process.
  • In the Heap tab, click Cause GC to invoke garbage collection, which enables the collection of heap data. When the operation completes, you will see a group of object types and the memory that has been allocated for each type. You can click Cause GC

Working with an emulator or device's file system

DDMS provides a File Explorer tab that allows you to view, copy, and delete files on the device. This feature is useful in examining files that are created by your application or if you want to transfer files to and from the device.

To work with an emulator or device's file system:

  • In the Devices tab, select the emulator that you want to view the file system for.
  • To copy a file from the device, locate the file in the File Explorer and click the Pull file button.
  • To copy a file to the device, click the Push file button on the File Explorer tab.

 

Tracking memory allocation of objects

DDMS provides a feature to track objects that are being allocated to memory and to see which classes and threads are allocating the objects. This allows you to track, in real time, where objects are being allocated when you perform certain actions in your application. This information is valuable for assessing memory usage that can affect application performance.

To track memory allocation of objects:

  • In the Devices tab, select the process that you want to enable allocation tracking for.
  • In the Allocation Tracker tab, click the Start Tracking button to begin allocation tracking. At this point, anything you do in your application will be tracked.
  • Click Get Allocations to see a list of objects that have been allocated since you clicked on the Start Tracking button. You can click on Get Allocations again to append to the list new objects that that have been allocated.
  • To stop tracking or to clear the data and start over, click the Stop Tracking button.
  • Click on a specific row in the list to see more detailed information such as the method and line number of the code that allocated the object.

Avoid Multiple Window open at a time

In android when user click on the back button, the previous screen is visible but the current screen is also open in background which speeds down the app. We need to close the current window on back button click. We need to override the back button click event for this.

Here is the example to override the back button click event:

var win = Titanium.UI.createWindow({  
    title:'Window 1',
    backgroundColor:'#fff',
    layout:"vertical"
});

var label1 = Titanium.UI.createLabel({ 
	top: 50,
	color:'#999',
	text:'I am Window 1',
	font:{fontSize:20,fontFamily:'Helvetica Neue'},
	textAlign:'center',
	width:'auto'
});


// Create a Button.
var buttonNext = Ti.UI.createButton({
	title : 'New Window',
	height : '47dp',
	width : '90%',
	top : 20,
});

// Listen for click events.
buttonNext.addEventListener('click', function() {
	Ti.API.info("Next Window Button Clicked");
	var win2 = Titanium.UI.createWindow({  
    title:'Window 2',
    backgroundColor:'#fff',
    layout:"vertical"
});
win2.addEventListener('android:back', function(e) {
	Ti.API.info("Back Button Clicked");
    win2.close();
    alert("Sub Window Closed");
    });
 var label2 = Titanium.UI.createLabel({
	top: 50,
	color:'#999',
	text:'I am Window 2',
	font:{fontSize:20,fontFamily:'Helvetica Neue'},
	textAlign:'center',
	width:'auto'
});
 
 win2.add(label2);
 Ti.API.info("Label2 Added");
  win2.open();
  Ti.API.info("Win2 open");
});
        

In the above example we created an eventListener on win2. When we press the back button, the previous screen is visible to the user and the current screen will be closed.

win2.addEventListener('android:back', function(e) {
	Ti.API.info("Back Button Clicked");
    win2.close();
    alert("Sub Window Closed");
    }); 

 

Hope it helps !

Anuj Khurana

anuj.khurana@oodlestechnologies.com

http://oodlestechnologies.com/

GOOGLE MAPS IN TITANIUM

June 20, 2012 by ARPIT SHARMA

Here, you'll learn how to use Google Maps in Titanium to visually represent location data via maps, annotations and  routes. The context of location is one of the most powerful features of mobile apps, and soon you'll be equipped to visualize that data using native UI components through Titanium.

  • Display a MapView.
  • Annotations.
  • Routes(iOS only).

Display a MapView : 

The MapView allows mobile device's to view geographic data and add annotations and routes. In its most basic form, the MapView can simply display a basic map using latitude and longitude.

var win = Ti.UI.createWindow();

var mapView = Titanium.Map.createView({
    mapType : Titanium.Map.STANDARD_TYPE,
    region : {latitude:37.389569, longitude:-122.050212,latitudeDelta:0.1, longitudeDelta:0.1},             
    animate : true,
    regionFit : true,
    userLocation : false
});

win.add(mapview);

win.open();

  • mapType : Indicates what type of map should be displayed.(Ti.Map.STANDARD_TYPE, Ti.Map.SATELLITE_TYPE  and Ti.Map.HYBRID_TYPE ).
  • regionThis is an object that contains the 4 properties defining the visible area of the MapView.(latitude and longitude of a region can be represented with a different level of zoom using latitudeDelta and longitudeDelta properties).

  • animate :  A boolean that indicates whether or not map actions, like opening and adding annotations, should be animated.

  • userLocationA boolean that indicates if the map should attempt to fit the MapView into the region in the visible view.

  • userLocation : A boolean that indicates if the map should show the user's current device location as a blue dot on the map.

There are 2 more components annotations and routes. They allow us to add places of interest to our maps as well as plot paths between them.

Annotations :

Annotations, created with the Ti.Map.createAnnotation() function, allow us to mark places on MapViews with pins, images, and text. We can add number of annotation in a MapView by using array.Let'smodify the basic MapView example.

var win = Ti.UI.createWindow();

var annotations1 = Ti.Map.createAnnotation({
        latitude: 37.389569,
        longitude: -122.050212,
        title: 'Title A',
        subtitle: 'Subtitle A',
        animate: true,
        image:'pin.png',
        leftButton: 'google.jpg'
   });
    
var annotations2 = Ti.Map.createAnnotation({
        latitude: 37.422502,
        longitude: -122.0855498,
        title: 'Title B',
        subtitle: 'Subtitle B',
        image:'pin.png',
        animate: true,
   });
    
var annotations = [annotations1, annotations2];
var mapview = Titanium.Map.createView({
    mapType: Titanium.Map.STANDARD_TYPE,
    region: {latitude:37.389569, longitude:-122.050212, latitudeDelta:0.02, longitudeDelta:0.02},       
    animate:true,
    regionFit:true,
    userLocation:false,
    annotations: annotations
});
win.add(mapview);
win.open();

Routes(iOS only)

Routes are an iOS-only feature. They allow us to draw paths between locations on a MapView. These paths can be driving directions, walking paths etc, to connect point A to point B.

var win = Ti.UI.createWindow();

var annotations1 = Ti.Map.createAnnotation({
        latitude: 37.389569,
        longitude: -122.050212,
        title: 'Title A',
        subtitle: 'Subtitle A',
        animate: true,
        image:'pin.png',
        leftButton: 'google.jpg'
   });
    
var annotations2 = Ti.Map.createAnnotation({
        latitude: 37.422502,
        longitude: -122.0855498,
        title: 'Title B',
        subtitle: 'Subtitle B',
        image:'pin.png',
        animate: true,
   });
    
var annotations = [annotations1, annotations2];
var mapview = Titanium.Map.createView({
    mapType: Titanium.Map.STANDARD_TYPE,
    region: {latitude:37.389569, longitude:-122.050212, latitudeDelta:0.02, longitudeDelta:0.02},        
    animate:true,
    regionFit:true,
    userLocation:false,
    annotations: annotations
});
win.add(mapview);
var socure = [37.389569, -122.050212];
var destination = [37.422502, -122.0855498];
var mode = "d";

var url = "http://maps.google.com/maps?saddr="+socure+"&daddr="+destination+"&f=d&sensor=true&doflg=ptm&hl=en&dirflg="+mode+"&output=kml";          

var xhr = Titanium.Network.createHTTPClient();
xhr.open('GET',url);
xhr.onload = function()
{
    var xml = this.responseXML;
    var coords = xml.documentElement.getElementsByTagName("LineString");
    
    var points = [];
    for(var cc=0; cc < coords.length; cc++)
    {
        var line = coords.item(cc);
        var str = line.firstChild.text.split(" ");
        for(dd = 0; dd < str.length; dd++)
        {
            var loc = str[dd].split(',');
            if(loc[0] && loc[1])
            {
                points.push({latitude: loc[1],longitude: loc[0]});
            }
        }
     }
     var route = {name:'mapRoute', points:points, color: "blue", width:4};
	mapview.addRoute(route);
}
xhr.send();
win.open();

You can change the color , width and mode of direction.

d = Driving Direction

w = Walking Direction 

Arpit Sharma
arpit.sharma@oodlestechnologies.com

http://oodlestechnologies.com/

Powered byApache Solr

Follow Us

Recent Entries