110
tiConf.eu, valencia, 24/02/2013 Native iOS & Android Modules Extending Titanium

Extending Titanium with native iOS and Android modules

  • Upload
    omorandi

  • View
    36.634

  • Download
    4

Embed Size (px)

DESCRIPTION

This is the presentation used for the workshop on Titanium module development held at tiConf 2013 in Valencia

Citation preview

Page 1: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013

Native iOS & Android Modules

Extending Titanium

Page 2: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013

Olivier MorandiSoftware en!ineer

http://[email protected]@olivier_morandihttps://github.com/omorandi

2

Page 3: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013

Module development is so

2010

Page 4: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013

Why Bother?

• To levera!e native features★ Underlyin! OS★ 3rd party libraries

• Performance★ To optimize the User Experience

4

Page 5: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013

Learnin! Resources

Page 7: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013 7

Page 8: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013

• Titanium Mobile SDK★ https://!ithub.com/appcelerator/

titanium_mobile

• Example modules from Appcelerator★ https://!ithub.com/appcelerator/

titanium_modules

8

Source code

Page 9: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013

Follow these guys

• Aaron K. Saunders: https://!ithub.com/aaronksaunders

• Ben Bahrenbur!: https://!ithub.com/benbahrenbur!

• Christian Sullivan: https://!ithub.com/euforic

• David Bankier: https://!ithub.com/dbankier

• Jordi Domenec: https://!ithub.com/iamyellow

• Marcel Pociot: https://!ithub.com/mpociot

• Matt Apperson: https://!ithub.com/mattapperson

• Paul Mietz E!li: https://!ithub.com/pe!li

• Ruben Fonseca: https://!ithub.com/rubenfonseca

• Russ Frank: https://!ithub.com/russfrank

9

Page 10: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013

Inside Titanium(A bit of architecture)

Page 11: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013 11

Titanium cli (node.js) + python scripts

Page 12: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013 12

Runtime (iOS)

Titanium Modules

(API)

JS APP

Parser

Interpreter

IOS SDK

Bytecode!en

Java

Scrip

tCor

e

objective-cC++

KRO

LL B

RIDG

E

Page 13: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013 12

Runtime (iOS)

Titanium Modules

(API)

JS APP

Parser

Interpreter

IOS SDK

Bytecode!en

Java

Scrip

tCor

e

NO JIT

objective-cC++

KRO

LL B

RIDG

E

Page 14: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013

Titanium Modules

(API)

JS APP

Parser

Native Code

Android SDK

Native Code!en

KRO

LL B

RIDG

E

13

Runtime (Android)

JavaC++

V8

OPT

Page 15: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013

Titanium Modules

(API)

JS APP

Parser

Native Code

Android SDK

Native Code!en

KRO

LL B

RIDG

E

13

Runtime (Android)

JavaC++

V8

OPT

Page 16: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013

Titanium Modules

(API)

JS APP

Parser

Native Code

Android SDK

Native Code!en

KRO

LL B

RIDG

E

13

Runtime (Android)

JavaC++

V8

OPT

Page 17: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013

Terminology

14

var win1 = Titanium.UI.createWindow({ title:'Hello World', backgroundColor:'white'});

var label1 = Titanium.UI.createLabel({ color:'black', textAlign:'center', width: 100});

label1.text = 'howdy?';win1.add(label1);

win1.open();

Page 18: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013

Terminology

14

var win1 = Titanium.UI.createWindow({ title:'Hello World', backgroundColor:'white'});

var label1 = Titanium.UI.createLabel({ color:'black', textAlign:'center', width: 100});

label1.text = 'howdy?';win1.add(label1);

win1.open();

moduleobject

Page 19: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013

Terminology

14

var win1 = Titanium.UI.createWindow({ title:'Hello World', backgroundColor:'white'});

var label1 = Titanium.UI.createLabel({ color:'black', textAlign:'center', width: 100});

label1.text = 'howdy?';win1.add(label1);

win1.open();

moduleobject

Objects of t

he

Titanium API are

injected in th

e JS

environment at

app

startup

Page 20: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013

Terminology

14

var win1 = Titanium.UI.createWindow({ title:'Hello World', backgroundColor:'white'});

var label1 = Titanium.UI.createLabel({ color:'black', textAlign:'center', width: 100});

label1.text = 'howdy?';win1.add(label1);

win1.open();

factorymethod

Page 21: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013

Terminology

14

var win1 = Titanium.UI.createWindow({ title:'Hello World', backgroundColor:'white'});

var label1 = Titanium.UI.createLabel({ color:'black', textAlign:'center', width: 100});

label1.text = 'howdy?';win1.add(label1);

win1.open();

creation properties

Page 22: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013

Terminology

14

var win1 = Titanium.UI.createWindow({ title:'Hello World', backgroundColor:'white'});

var label1 = Titanium.UI.createLabel({ color:'black', textAlign:'center', width: 100});

label1.text = 'howdy?';win1.add(label1);

win1.open();

proxyobject

Page 23: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013

Terminology

14

var win1 = Titanium.UI.createWindow({ title:'Hello World', backgroundColor:'white'});

var label1 = Titanium.UI.createLabel({ color:'black', textAlign:'center', width: 100});

label1.text = 'howdy?';win1.add(label1);

win1.open();

view proxyobject

Page 24: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013

Terminology

14

var win1 = Titanium.UI.createWindow({ title:'Hello World', backgroundColor:'white'});

var label1 = Titanium.UI.createLabel({ color:'black', textAlign:'center', width: 100});

label1.text = 'howdy?';win1.add(label1);

win1.open();

proxy property

Page 25: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013

Terminology

14

var win1 = Titanium.UI.createWindow({ title:'Hello World', backgroundColor:'white'});

var label1 = Titanium.UI.createLabel({ color:'black', textAlign:'center', width: 100});

label1.text = 'howdy?';win1.add(label1);

win1.open();proxy

method

Page 26: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013

Proxies & Modules

Proxy

ViewProxy ViewModule

extends

has a

creates

15

mana!es

Native View TypeiOS UIView

Android View

extends

Page 27: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013

Proxies & Modules

Proxy

ViewProxy ViewModule

extends

has a

creates

15

mana!es

Native View TypeiOS UIView

Android View

State:properties

Actions: methods

Events:addEventListener(), fireEvent()

Interface

extends

Page 28: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013

Proxies & Modules

Proxy

ViewProxy ViewModule

extends

has a

creates

15

mana!es

Native View TypeiOS UIView

Android View

State:properties

Actions: methods

Events:addEventListener(), fireEvent()

Interface

Methods for the inte!ration within the application lifecycle•startup() (iOS)•shutdown() (iOS)•onAppCreate() (Android)

extends

Page 29: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013

Proxies & Modules

Proxy

ViewProxy ViewModule

extends

has a

creates

15

mana!es

Native View TypeiOS UIView

Android View

State:properties

Actions: methods

Events:addEventListener(), fireEvent()

Interface

Additional members for the inte!ration within the UI layout system:•add()•remove()•height•width•backgroundColor•...

Methods for the inte!ration within the application lifecycle•startup() (iOS)•shutdown() (iOS)•onAppCreate() (Android)

extends

Page 30: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013

Let’s create a module

Page 31: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013

• Create

• Develop

• Build

• Deploy

• Debu!

17

Page 32: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013

• Create

• Develop

• Build

• Deploy

• Debu!

17

Page 33: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013

Module Development

Page 34: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013

• Same as for Ti app development on iOS:★ Titanium SDK.★ Xcode

19

iOS Prerequisites

Page 35: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013

• Same as for Ti app development on Android:

★ Titanium SDK.

★ Android SDK (+ ANDROID_SDK environment variable)

• Additionally:

★ Android NDK (+ ANDROID_NDK environment variable)

★ Ant 1.7.1 (available in PATH)

★ !perf must be installed and in your system PATH.

★ [Eclipse]

20

Android Prerequisites

Page 36: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013 21

Create (cli)$ alias ti='~/Library/Application\ Support/Titanium/mobilesdk/osx/3.0.0.GA/ titanium.py'

OLD SCHOOL

Page 37: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013 21

Create (cli)$ alias ti='~/Library/Application\ Support/Titanium/mobilesdk/osx/3.0.0.GA/ titanium.py'

$ ti create --type=module --id=ti.conf.sample --name=ticonfsample --platform=iphone --dir=./ios

OLD SCHOOL

Page 38: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013 21

Create (cli)$ alias ti='~/Library/Application\ Support/Titanium/mobilesdk/osx/3.0.0.GA/ titanium.py'

$ ti create --type=module --id=ti.conf.sample --name=ticonfsample --platform=iphone --dir=./ios

$ ti create --type=module--id=ti.conf.sample --name=ticonfsample --platform=android --dir=./android

OLD SCHOOL

Page 39: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013 22

Page 40: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013 22

Page 41: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013 22

Page 42: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013 22

Page 43: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013

Create (Ti Studio)

23

Page 44: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013

Create (Ti Studio)

24

Page 45: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013

Create (Ti Studio)

25

Page 46: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013

Module Boilerplate

26

Page 47: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013

Module Boilerplate

27

Page 48: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013 28

Build & Install (cli)

$ ./build.py$ unzip -uo ti.conf.sample-iphone-0.1.zip -d ~/Library/Application\ Support/Titanium/

Page 49: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013 28

Build & Install (cli)

$ ./build.py$ unzip -uo ti.conf.sample-iphone-0.1.zip -d ~/Library/Application\ Support/Titanium/

$ ant$ unzip -uo dist/ti.conf.sample-android-0.1.zip -d ~/Library/Application\ Support/Titanium/

Page 50: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013

Build (Ti Studio)

29

Page 51: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013

Build & Install (Ti Studio)

30

Page 52: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013

Deploy

31

var ticonfsample = require('ti.conf.sample');

Ti.API.info(ticonfsample.example());

Ti.API.info("module exampleProp is => " + ticonfsample.exampleProp);ticonfsample.exampleProp = "This is a test value";

<?xml version="1.0" encoding="UTF-8"?><ti:app xmlns:ti="http://ti.appcelerator.org"> <id>com.omorandi.ticonftest</id> <!-- ... -->

<modules> <module platform="iphone">ti.conf.sample</module> <module platform="android">ti.conf.sample</module> </modules></ti:app>

app.js

tiapp.xml

Page 53: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013

• Methods

• Passin! ar!uments

• Returnin! values

• Exceptions

• Usin! properties

• Proxies

• Events

• Callbacks

• ViewProxies

32

Agenda

Page 54: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013

Proxy/Module Methods

33

-(id)methodName:(id)args{ NSString result = @"Hello World”;

//do something

return result;}

return value

Page 55: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013

Proxy/Module Methods

33

-(id)methodName:(id)args{ NSString result = @"Hello World”;

//do something

return result;}

return value

-(void)methodName:(id)args{ //do something}

no return value

Page 56: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013

Proxy/Module Methods

33

-(id)methodName:(id)args{ NSString result = @"Hello World”;

//do something

return result;}

return value

-(void)methodName:(id)args{ //do something}

no return value

@Kroll.methodpublic String methodName(){

String result = "Hello world"; //do something

return result;}

return valueno ar!s

Page 57: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013

Proxy/Module Methods

33

-(id)methodName:(id)args{ NSString result = @"Hello World”;

//do something

return result;}

return value

-(void)methodName:(id)args{ //do something}

no return value

@Kroll.methodpublic String methodName(){

String result = "Hello world"; //do something

return result;}

return valueno ar!s

@Kroll.methodpublic void methodName(String value){ //do something}

no return value

Page 58: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013

Example: xml2json module

34

Expected API

var xml2json = require('ti.xml2json');

var json = xml2json.convert(xmlDoc);

https://!ithub.com/omorandi/TiXml2Json

Page 59: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013

Implementation

35

@implementation TiXml2jsonModule

-(NSDictionary) convertXml:(NSString)xmlString{ NSDictionary *jsObj;

//do conversion stuff

return jsObj;}

-(id)convert:(id)args{ ENSURE_SINGLE_ARG(args, NSString); return [self convertXml:args];}

@end

Page 60: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013

Implementation

35

@implementation TiXml2jsonModule

-(NSDictionary) convertXml:(NSString)xmlString{ NSDictionary *jsObj;

//do conversion stuff

return jsObj;}

-(id)convert:(id)args{ ENSURE_SINGLE_ARG(args, NSString); return [self convertXml:args];}

@end

NSArray of ar!uments

Page 61: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013

Implementation

35

@implementation TiXml2jsonModule

-(NSDictionary) convertXml:(NSString)xmlString{ NSDictionary *jsObj;

//do conversion stuff

return jsObj;}

-(id)convert:(id)args{ ENSURE_SINGLE_ARG(args, NSString); return [self convertXml:args];}

@end

NSArray of ar!uments#define ENSURE_SINGLE_ARG(x,t)\{ \ x = (t*)[x objectAtIndex:0]; \} \

TiBase.h

Page 62: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013

Utility Macros

36

#define ENSURE_CLASS(x,t)#define ENSURE_CLASS_OR_NIL(x,t)#define ENSURE_TYPE(x,t)#define ENSURE_TYPE_OR_NIL(x,t)#define ENSURE_ARG_COUNT(x,c)#define ENSURE_SINGLE_ARG(x,t)#define ENSURE_SINGLE_ARG_OR_NIL(x,t)#define ENSURE_DICT(x)#define ENSURE_ARRAY(x)#define ENSURE_STRING(x)#define THROW_INVALID_ARG(m)

...

TiBase.h

Page 63: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013

Types

37

NSStringNSDictionaryNSArrayNSNumberNSDateNSNullTiProxy

Supported Directly

#import "TiUtils.h"

CGFloat f = [TiUtils floatValue:arg];NSInteger f = [TiUtils intValue:arg];

NSString *value = [TiUtils stringValue:arg];

TiColor *bgcolor = [TiUtils colorValue:arg];UIColor *backgroundColor = [bgcolor color];

Conversion Utilities

Page 64: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013

Return Values

• Sin!le Value (NSStrin!, NSNumber, …)

• Collections (NSArray)★ Converted into a JS Array object

• Dictionary (NSDictionary)★ Converted into a JS object★ key->value ===> property->value

• Proxy (TiProxy)

38

Page 65: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013

Return Values

• Sin!le Value (NSStrin!, NSNumber, …)

• Collections (NSArray)★ Converted into a JS Array object

• Dictionary (NSDictionary)★ Converted into a JS object★ key->value ===> property->value

• Proxy (TiProxy)

38

RETURN AUTORELEASED OBJECTS

Page 66: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013

xml2json Android

39

import org.appcelerator.kroll.KrollDict;

@Kroll.module(name="Tixml2json", id="ti.xml2json")public class Tixml2jsonModule extends KrollModule{

@Kroll.methodpublic KrollDict convert(String xml)

{ KrollDict json = null;

//do conversion stuff

return json; }

}

Page 67: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013

xml2json Android

39

import org.appcelerator.kroll.KrollDict;

@Kroll.module(name="Tixml2json", id="ti.xml2json")public class Tixml2jsonModule extends KrollModule{

@Kroll.methodpublic KrollDict convert(String xml)

{ KrollDict json = null;

//do conversion stuff

return json; }

}

public class KrollDict extends HashMap<String, Object>

KrollDict.java

Page 68: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013

Types

40

StringintfloatdoublebooleanObject[]HashMap<String, Object>TiProxy

import org.appcelerator.titanium.util.TiConvert;

int val = TiConvert.toInt(obj);float val = TiConvert.toFloat(obj);double val = TiConvert.toDouble(obj);boolean val = TiConvert.toBoolean(obj);int color = TiConvert.toColor(str);...

Supported Directly Conversion Utilities

http://builds.appcelerator.com.s3.amazonaws.com/module-apidoc/2.0.0/android/or!/appcelerator/titanium/util/TiConvert.html

Page 69: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013

Return Values

• Sin!le Value (Strin!, Inte!er, …)

• Collections (Object[])★ Converted into a JS Array object

• Dictionary (HashMap<Strin!, Object>)★ Converted into a JS object★ key->value ===> property->value

• Proxy (TiProxy)

41

Page 70: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013

Polymorphic Methods

42

-(id)convert:(id)args{ ENSURE_ARG_COUNT(args, 1);

id arg = [args objectAtIndex:0]; if ([arg isKindOfClass:[NSString class]]) { return [self convertFromString:arg]; } else if ([arg isKindOfClass:[TiBlob class]]) { return [self convertFromData:arg]; } else { [self throwException:@"Expected blob or string argument"

subreason:nil location:CODELOCATION]; }}

Page 71: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013

Polymorphic Methods

43

public KrollDict convertFromString(String xml);public KrollDict convertFromBlob(TiBlob blob) @Kroll.methodpublic String convert(Object arg) {

if (arg instanceof String) { return "string"; } if (arg instanceof TiBlob) { return "blob"; } throw new IllegalArgumentException("Invalid argument type,

expected blob or string");}

Page 72: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013

Varargs

44

-(void) varArgsMethod:(id)args{ for (int i = 0; i < [args count]; i++) { id arg = [args objectAtIndex:i]; // do something with arg }}

Page 73: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013

Varargs

45

@Kroll.methodpublic void varArgsMethod(Object[] args) {

for (int i = 0; i < args.length; i++) { Object arg = args[i];

// do something with arg }}

Page 74: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013

Properties

46

module.propertyName = "HELLO";

Ti.API.info("Property: " + module.propertyName);

set

!et

Page 75: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013

Properties

47

@interface TiMyModule: TiModule

@property (nonatomic, readwrite, retain) NSString* propertyName;

@end

@implementation TiMyModule: TiModule

@synthesize propertyName;

@end

TiMyModule.h

TiMyModule.m

Page 76: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013

Properties: Setter/Getter

48

- (void) setPropertyName:(id)args { // set property and do stuff}

- (id) propertyName { // do something and return value;}

Page 77: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013

Properties: Setter/Getter

49

@Kroll.module(name="My", id="ti.my")public class MyModule extends KrollModule{

private String propertyName; @Kroll.getProperty @Kroll.method public String getPropertyName() { return propertyName; } @Kroll.setProperty @Kroll.method public void setPropertyName(String value) { propertyName = value; }}

Page 78: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013

Constants

50

var smsModule = require('ti.ios.sms');

function sendCallback(e){ switch (e.result) {

case sms.SENT: result = 'SENT'; break; case sms.FAILED: result = 'FAILED'; break; case sms.CANCELLED: result = 'CANCELLED'; break; } Ti.API.info("Property: " + module.propertyName);}

Page 79: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013

Constants

51

//create the accessor methods for the SENT, CANCELLED and FAILED constantsMAKE_SYSTEM_PROP(SENT,MessageComposeResultSent);MAKE_SYSTEM_PROP(CANCELLED,MessageComposeResultCancelled);MAKE_SYSTEM_PROP(FAILED,MessageComposeResultFailed);

https://!ithub.com/omorandi/TiSMSDialo!/blob/master/Classes/ComOmorandiSMSDialo!Proxy.m

Page 80: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013

Constants

51

//create the accessor methods for the SENT, CANCELLED and FAILED constantsMAKE_SYSTEM_PROP(SENT,MessageComposeResultSent);MAKE_SYSTEM_PROP(CANCELLED,MessageComposeResultCancelled);MAKE_SYSTEM_PROP(FAILED,MessageComposeResultFailed);

https://!ithub.com/omorandi/TiSMSDialo!/blob/master/Classes/ComOmorandiSMSDialo!Proxy.m

#define MAKE_SYSTEM_PROP(name,map) \-(NSNumber*)name \{\return [NSNumber numberWithInt:map];\}\

TiBase.h

Page 81: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013

Constants

51

//create the accessor methods for the SENT, CANCELLED and FAILED constantsMAKE_SYSTEM_PROP(SENT,MessageComposeResultSent);MAKE_SYSTEM_PROP(CANCELLED,MessageComposeResultCancelled);MAKE_SYSTEM_PROP(FAILED,MessageComposeResultFailed);

https://!ithub.com/omorandi/TiSMSDialo!/blob/master/Classes/ComOmorandiSMSDialo!Proxy.m

#define MAKE_SYSTEM_PROP(name,map) \-(NSNumber*)name \{\return [NSNumber numberWithInt:map];\}\

TiBase.h

@Kroll.module(name="Sms", id="ti.android.sms")public class SmsModule extends KrollModule{ @Kroll.constant public static final int SENT = 0; @Kroll.constant public static final int CANCELLED = -1; @Kroll.constant public static final int FAILED = -2;}

Page 82: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013

Proxy Objects

52

var smsModule = require('ti.ios.sms');

//create the smsDialog objectvar smsDialog = smsModule.createSMSDialog({ recipients: ['+123456789'], messageBody: 'hello'});

smsDialog.open();

Page 83: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013

Creating a Proxy

53

@interface TiIosSmsSMSDialogProxy: TiProxy<MFMessageComposeViewControllerDelegate>

@end

@implementation TiIosSmsSMSDialogProxy

- (void)open:(id)args{

// retrieve properties (either set on creation, or later)

NSArray * recipients = [self valueForUndefinedKey:@"recipients"];NSString * messageBody= [TiUtils stringValue:[self valueForUndefinedKey:@"messageBody"]];

// do stuff

}

@end

TiIosSmsSMSDialo!Proxy.h

TiIosSmsSMSDialo!Proxy.m

Page 84: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013

Proxy Objects

54

var smsModule = require('ti.android.sms');

//create the sms objectvar sms = smsModule.createSms({ recipient: '+123456789', messageBody: 'hello'});

sms.send();

Page 85: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013

Creating a Proxy

55

@Kroll.proxy(creatableInModule=SmsModule.class)public class SmsProxy extends KrollProxy{ private String messageBody = null; private String recipient = null;

// Constructor public SmsProxy() { super(); }

// Handle creation options @Override public void handleCreationDict(KrollDict options) { super.handleCreationDict(options); if (options.containsKey("messageBody")) { messageBody = (String)options.get("messageBody"); } if (options.containsKey("recipient")) { recipient = (String)options.get("recipient"); } }

@Kroll.method public void send() {

// send the message}

}

Page 86: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013

Events

56

// create the Module objectvar tibarcode = require('ti.barcode');

var scanner = tibarcode.createScanner();

// success event listenerscanner.addEventListener('success', function(e) { var code = e.barcode; var type = e.type; alert('Found code: ' + code + ' type: ' + type);});

Notify a chan!e of state, or an asynchronous event

Page 87: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013

Events

57

@implementation TiBarcodeScannerProxy

// Scanner Delegate

- (void) imagePickerController: (UIImagePickerController*)reader didFinishPickingMediaWithCode:(NSString*)code andType:(NSString*)type

{ if ([self _hasListeners:@"success"]){ NSDictionary *results = [NSDictionary dictionaryWithObjectsAndKeys: code, @"code", type, @"type", nil];

[self fireEvent:@"success" withObject:results]; }}

@end

Page 88: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013

Events

58

public class ScannerProxy extends KrollProxy{

void onScannerResult(String code, String type) {

if (hasListeners("success")) { KrollDict event = new KrollDict(); event.put("code", code); event.put("type", type); fireEvent("success", event); } }}

Page 89: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013

Callbacks

59

// let's not freeze on huge xml dataxml2json.convertAsync(xmlDoc, function(data) { Ti.API.info("JSON object: " + JSON.stringify(data.json));});

Notify the result of an asynchronous action

Page 90: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013

Callbacks

60

-(void)convertAsync:(id)args{ ENSURE_ARG_COUNT(args, 2); id xml = [args objectAtIndex:0]; KrollCallback *cb = [args objectAtIndex:1]; ENSURE_TYPE(cb, KrollCallback); //pass just the first (string|blob) arg to convertXml() dispatch_async(dispatchQueue, ^(void) { id result = [self convertXml:xml]; NSDictionary *cbArgs = [NSDictionary dictionaryWithObject:result forKey:@"json"]; [self _fireEventToListener:@"success" withObject:cbArgs listener:cb

thisObject:nil]; });}

Page 91: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013

Callbacks

61

@Kroll.methodpublic KrollDict convertAsync(String xml, final KrollFunction callback){

new Thread() { @Override public void run() { KrollDict json = null;

//do conversion stuff

KrollDict data = new KrollDict(); event.put("json", json); callback.call(getKrollObject(), data); } }.start();}

Page 92: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013

ViewProxy

62

View

Prox

y

View

Nativ

e Vi

ews

Hier

arch

y

Methods

Properties (!et/set)

Events

Holds the state of a view

Mana!es the native view hierarchy

Page 93: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013

ViewProxy

62

View

Prox

y

View

Nativ

e Vi

ews

Hier

arch

y

Methods

Properties (!et/set)

Events

Holds the state of a view

Mana!es the native view hierarchy

JS THREAD

Page 94: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013

ViewProxy

62

View

Prox

y

View

Nativ

e Vi

ews

Hier

arch

y

Methods

Properties (!et/set)

Events

Holds the state of a view

Mana!es the native view hierarchy

JS THREAD UI THREAD

Page 95: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013

ViewProxy

62

View

Prox

y

View

Nativ

e Vi

ews

Hier

arch

y

Methods

Properties (!et/set)

Events

Holds the state of a view

Mana!es the native view hierarchy

JS THREAD UI THREAD

Mostly async

Page 96: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013

Super-Smooth TableView

63

• API• createMessagesView(properties);• setMessages([]messages);• insert(message);• addEventListener(‘click’, callback);

Page 97: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013

Implementation

64

@implementation TiSmoothMessagesViewProxy

@synthesize msgs;

//other methods

-(void) insert:(id)args{ ENSURE_SINGLE_ARG(args, NSDictionary); [self.msgs insertMessageOnTop:[self messageFromDictionary:(NSDictionary*)args]];

[self makeViewPerformSelector:@selector(addMessage:) withObject:args createIfNeeded:YES waitUntilDone:NO];

}

@end

Messa!esViewProxy

@interface TiSmoothMessagesViewProxy : TiViewProxy

@property (nonatomic, retain) MessagesCollection *msgs; //model

@end

TiSmoothMessa!esViewProxy.h

TiSmoothMessa!esViewProxy.m

Page 98: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013

Implementation

64

@implementation TiSmoothMessagesViewProxy

@synthesize msgs;

//other methods

-(void) insert:(id)args{ ENSURE_SINGLE_ARG(args, NSDictionary); [self.msgs insertMessageOnTop:[self messageFromDictionary:(NSDictionary*)args]];

[self makeViewPerformSelector:@selector(addMessage:) withObject:args createIfNeeded:YES waitUntilDone:NO];

}

@end

Messa!esViewProxy

@interface TiSmoothMessagesViewProxy : TiViewProxy

@property (nonatomic, retain) MessagesCollection *msgs; //model

@end

TiSmoothMessa!esViewProxy.h

TiSmoothMessa!esViewProxy.m

create the view and call addMessa!e on the UI thread

Page 99: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013

Implementation

65

@implementation TiSmoothMessagesView

-(void)initializeState{ [super initializeState]; viewController = [[InboxViewController alloc] initWithStyle:UITableViewStylePlain];

UITableView *tableView = viewController.tableView; [self addSubview:tableView];}

-(void)addMessage:(InboxMessage*)message{ ENSURE_UI_THREAD(addMessage, message); [viewController addMessageOnTop:message];}

-(void)frameSizeChanged:(CGRect)frame bounds:(CGRect)bounds{ [TiUtils setView: viewController.tableView positionRect:bounds];}

@end

Messa!esView

@interface TiSmoothMessagesView : TiUIView {

MessagesViewController *viewController;}

@end

TiSmoothMessa!esView.h

TiSmoothMessa!esView.m

Page 100: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013

Implementation

65

@implementation TiSmoothMessagesView

-(void)initializeState{ [super initializeState]; viewController = [[InboxViewController alloc] initWithStyle:UITableViewStylePlain];

UITableView *tableView = viewController.tableView; [self addSubview:tableView];}

-(void)addMessage:(InboxMessage*)message{ ENSURE_UI_THREAD(addMessage, message); [viewController addMessageOnTop:message];}

-(void)frameSizeChanged:(CGRect)frame bounds:(CGRect)bounds{ [TiUtils setView: viewController.tableView positionRect:bounds];}

@end

Messa!esView

@interface TiSmoothMessagesView : TiUIView {

MessagesViewController *viewController;}

@end

TiSmoothMessa!esView.h

TiSmoothMessa!esView.m

called by Titanium at view creation

Page 101: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013

Implementation

65

@implementation TiSmoothMessagesView

-(void)initializeState{ [super initializeState]; viewController = [[InboxViewController alloc] initWithStyle:UITableViewStylePlain];

UITableView *tableView = viewController.tableView; [self addSubview:tableView];}

-(void)addMessage:(InboxMessage*)message{ ENSURE_UI_THREAD(addMessage, message); [viewController addMessageOnTop:message];}

-(void)frameSizeChanged:(CGRect)frame bounds:(CGRect)bounds{ [TiUtils setView: viewController.tableView positionRect:bounds];}

@end

Messa!esView

@interface TiSmoothMessagesView : TiUIView {

MessagesViewController *viewController;}

@end

TiSmoothMessa!esView.h

TiSmoothMessa!esView.m

called by Titanium at view creation

called by Titanium for notifyin! a chan!e in frame size

Page 102: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013 66

//// PLACE ANY BUILD DEFINITIONS IN THIS FILE AND THEY WILL BE // PICKED UP DURING THE APP BUILD FOR YOUR MODULE//

OTHER_LDFLAGS=$(inherited) -framework AVFoundation -framework CoreMedia -framework CoreVideo -framework QuartzCore /usr/lib/libiconv.dylib

module.xcconfi!

Module Packa!e(.zip)

build & packa!e

app bundle

Page 103: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013 66

//// PLACE ANY BUILD DEFINITIONS IN THIS FILE AND THEY WILL BE // PICKED UP DURING THE APP BUILD FOR YOUR MODULE//

OTHER_LDFLAGS=$(inherited) -framework AVFoundation -framework CoreMedia -framework CoreVideo -framework QuartzCore /usr/lib/libiconv.dylib

module.xcconfi!

Module Packa!e(.zip)

build & packa!e

app bundle

Page 104: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013 67

<?xml version="1.0" encoding="UTF-8"?><ti:module xmlns:ti="http://ti.appcelerator.org" xmlns:android="http://schemas.android.com/apk/res/android"> <iphone> </iphone> <android xmlns:android="http://schemas.android.com/apk/res/android"> <manifest> <uses-permission android:name="android.permission.SEND_SMS" />

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

<application> <activity android:name="ti.conf.sample.MyCustomActivity"> </activity> </application> </manifest> </android> <mobileweb> </mobileweb></ti:module>

timodule.xml

Module Packa!e(.zip)

build & packa!e AndroidManifest.xml

app.apk

Page 105: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013

Debu!!in!

Page 106: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013

Create a debug build

69

$ sed s/Release/Debug/ build.py > build_debug.py

168: rc = os.system("xcodebuild -sdk iphoneos -configuration Debug")171: rc = os.system("xcodebuild -sdk iphonesimulator -configuration Debug")

build_debu!.py

168: rc = os.system("xcodebuild -sdk iphoneos -configuration Release")171: rc = os.system("xcodebuild -sdk iphonesimulator -configuration Release")

build.py

Page 107: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013

Debugging

70

Page 108: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013

Debug Logs

71

@Kroll.module(name="Ticonfsample", id="ti.conf.sample")public class TiconfsampleModule extends KrollModule{

// Tag for debug log messages private static final String LCAT = "TiconfsampleModule";

// tells if debug logging has been enabled in the Titanium application private static final boolean DBG = TiConfig.LOGD;

@Kroll.method public void doSomething() { Log.d(LCAT, "doing something"); }}

Page 109: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013

Android DDMS

72

Page 110: Extending Titanium with native iOS and Android modules

tiConf.eu, valencia, 24/02/2013

Thank you!