Your SlideShare is downloading. ×
0
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Extending Titanium with native iOS and Android modules
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

Extending Titanium with native iOS and Android modules

37,765

Published on

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

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

Published in: Technology
2 Comments
27 Likes
Statistics
Notes
No Downloads
Views
Total Views
37,765
On Slideshare
0
From Embeds
0
Number of Embeds
21
Actions
Shares
0
Downloads
320
Comments
2
Likes
27
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. Extending Titanium Native iOS & Android ModulestiConf.eu, valencia, 24/02/2013
  • 2. Olivier Morandi Software engineer http://titaniumninja.com olivier.morandi@gmail.com @olivier_morandi https://github.com/omoranditiConf.eu, valencia, 24/02/2013 2
  • 3. Module development is so 2010tiConf.eu, valencia, 24/02/2013
  • 4. Why Bother? • To leverage native features ★ Underlying OS ★ 3rd party libraries • Performance ★ To optimize the User ExperiencetiConf.eu, valencia, 24/02/2013 4
  • 5. Learning ResourcestiConf.eu, valencia, 24/02/2013
  • 6. Official Appcelerator Guides • http://docs.appcelerator.com/titanium/latest/#!/guide/ Extending_Titanium_Mobile • http://docs.appcelerator.com/titanium/latest/#!/guide/ iOS_Module_Development_Guide • http://docs.appcelerator.com/titanium/latest/#!/guide/ Android_Module_Development_GuidetiConf.eu, valencia, 24/02/2013 6
  • 7. tiConf.eu, valencia, 24/02/2013 7
  • 8. Source code • Titanium Mobile SDK ★ https://github.com/appcelerator/ titanium_mobile • Example modules from Appcelerator ★ https://github.com/appcelerator/ titanium_modulestiConf.eu, valencia, 24/02/2013 8
  • 9. Follow these guys • Aaron K. Saunders: https://github.com/aaronksaunders • Ben Bahrenburg: https://github.com/benbahrenburg • Christian Sullivan: https://github.com/euforic • David Bankier: https://github.com/dbankier • Jordi Domenec: https://github.com/iamyellow • Marcel Pociot: https://github.com/mpociot • Matt Apperson: https://github.com/mattapperson • Paul Mietz Egli: https://github.com/pegli • Ruben Fonseca: https://github.com/rubenfonseca • Russ Frank: https://github.com/russfranktiConf.eu, valencia, 24/02/2013 9
  • 10. Inside Titanium (A bit of architecture)tiConf.eu, valencia, 24/02/2013
  • 11. Titanium cli (node.js) + python scriptstiConf.eu, valencia, 24/02/2013 11
  • 12. Runtime (iOS) JS APP Parser KROLL BRIDGE JavaScriptCore Bytecode Titanium Modules objective-c gen (API) C++ Interpreter IOS SDKtiConf.eu, valencia, 24/02/2013 12
  • 13. Runtime (iOS) JS APP Parser KROLL BRIDGE JavaScriptCore Bytecode Titanium Modules objective-c gen (API) C++ O JIT N Interpreter IOS SDKtiConf.eu, valencia, 24/02/2013 12
  • 14. Runtime (Android) JS APP V8 Parser KROLL BRIDGE Native Code Titanium Modules Java gen OPT (API) C++ Native Code Android SDKtiConf.eu, valencia, 24/02/2013 13
  • 15. Runtime (Android) JS APP V8 Parser KROLL BRIDGE Native Code Titanium Modules Java gen OPT (API) C++ Native Code Android SDKtiConf.eu, valencia, 24/02/2013 13
  • 16. Runtime (Android) JS APP V8 Parser KROLL BRIDGE Native Code Titanium Modules Java gen OPT (API) C++ Native Code Android SDKtiConf.eu, valencia, 24/02/2013 13
  • 17. Terminology 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();tiConf.eu, valencia, 24/02/2013 14
  • 18. Terminology module object 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();tiConf.eu, valencia, 24/02/2013 14
  • 19. Terminology module object 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(); he cts of t Obje A PI a re nium S Tita in the J cted pp inje nt at a ro nme envi p s tartutiConf.eu, valencia, 24/02/2013 14
  • 20. Terminology factory method 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();tiConf.eu, valencia, 24/02/2013 14
  • 21. Terminology var win1 = Titanium.UI.createWindow({ title:Hello World, creation backgroundColor:white properties }); var label1 = Titanium.UI.createLabel({ color:black, textAlign:center, width: 100 }); label1.text = howdy?; win1.add(label1); win1.open();tiConf.eu, valencia, 24/02/2013 14
  • 22. Terminology proxy object 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();tiConf.eu, valencia, 24/02/2013 14
  • 23. Terminology var win1 = Titanium.UI.createWindow({ title:Hello World, backgroundColor:white }); view proxy var label1 = Titanium.UI.createLabel({ object color:black, textAlign:center, width: 100 }); label1.text = howdy?; win1.add(label1); win1.open();tiConf.eu, valencia, 24/02/2013 14
  • 24. Terminology var win1 = Titanium.UI.createWindow({ title:Hello World, backgroundColor:white }); var label1 = Titanium.UI.createLabel({ color:black, textAlign:center, width: 100 }); proxy label1.text = howdy?; property win1.add(label1); win1.open();tiConf.eu, valencia, 24/02/2013 14
  • 25. Terminology 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); proxy win1.open(); methodtiConf.eu, valencia, 24/02/2013 14
  • 26. Proxies & Modules Native View Type Proxy iOS UIView Android View creates manages extends extends Module ViewProxy View has atiConf.eu, valencia, 24/02/2013 15
  • 27. Proxies & Modules Interface State: properties Actions: methods Events: addEventListener(), fireEvent() Native View Type Proxy iOS UIView Android View creates manages extends extends Module ViewProxy View has atiConf.eu, valencia, 24/02/2013 15
  • 28. Proxies & Modules Interface State: properties Actions: methods Events: addEventListener(), fireEvent() Native View Type Proxy iOS UIView Android View creates manages extends extends Module ViewProxy ViewMethods for the integration within theapplication lifecycle has a •startup() (iOS) •shutdown() (iOS) •onAppCreate() (Android)tiConf.eu, valencia, 24/02/2013 15
  • 29. Proxies & Modules Interface State: properties Actions: methods Events: addEventListener(), fireEvent() Native View Type Proxy iOS UIView Android View creates manages extends extends Module ViewProxy View Additional members for the integrationMethods for the integration within theapplication lifecycle within the UI layout system: •add() has a •startup() (iOS) •remove() •shutdown() (iOS) •height •onAppCreate() (Android) •width •backgroundColor •...tiConf.eu, valencia, 24/02/2013 15
  • 30. Let’s create a moduletiConf.eu, valencia, 24/02/2013
  • 31. • Create • Develop • Build • Deploy • DebugtiConf.eu, valencia, 24/02/2013 17
  • 32. • Create • Develop • Build • Deploy • DebugtiConf.eu, valencia, 24/02/2013 17
  • 33. Module DevelopmenttiConf.eu, valencia, 24/02/2013
  • 34. iOS Prerequisites • Same as for Ti app development on iOS: ★ Titanium SDK. ★ XcodetiConf.eu, valencia, 24/02/2013 19
  • 35. Android Prerequisites • 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) ★ gperf must be installed and in your system PATH. ★ [Eclipse]tiConf.eu, valencia, 24/02/2013 20
  • 36. Create (cli) $ alias ti=~/Library/Application Support/Titanium/mobilesdk/osx/3.0.0.GA/ titanium.py OL SCHO OLDtiConf.eu, valencia, 24/02/2013 21
  • 37. 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 OL SCHO OLDtiConf.eu, valencia, 24/02/2013 21
  • 38. 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 OL SCHO OLDtiConf.eu, valencia, 24/02/2013 21
  • 39. tiConf.eu, valencia, 24/02/2013 22
  • 40. tiConf.eu, valencia, 24/02/2013 22
  • 41. tiConf.eu, valencia, 24/02/2013 22
  • 42. tiConf.eu, valencia, 24/02/2013 22
  • 43. Create (Ti Studio)tiConf.eu, valencia, 24/02/2013 23
  • 44. Create (Ti Studio)tiConf.eu, valencia, 24/02/2013 24
  • 45. Create (Ti Studio)tiConf.eu, valencia, 24/02/2013 25
  • 46. Module BoilerplatetiConf.eu, valencia, 24/02/2013 26
  • 47. Module BoilerplatetiConf.eu, valencia, 24/02/2013 27
  • 48. Build & Install (cli) $ ./build.py $ unzip -uo ti.conf.sample-iphone-0.1.zip -d ~/Library/Application Support/ Titanium/tiConf.eu, valencia, 24/02/2013 28
  • 49. 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/tiConf.eu, valencia, 24/02/2013 28
  • 50. Build (Ti Studio)tiConf.eu, valencia, 24/02/2013 29
  • 51. Build & Install (Ti Studio)tiConf.eu, valencia, 24/02/2013 30
  • 52. Deploy tiapp.xml <?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 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";tiConf.eu, valencia, 24/02/2013 31
  • 53. Agenda • Methods • Events • Passing • Callbacks arguments • ViewProxies • Returning values • Exceptions • Using properties • ProxiestiConf.eu, valencia, 24/02/2013 32
  • 54. Proxy/Module Methods return value -(id)methodName:(id)args { NSString result = @"Hello World”; //do something return result; }tiConf.eu, valencia, 24/02/2013 33
  • 55. Proxy/Module Methods return value -(id)methodName:(id)args { NSString result = @"Hello World”; //do something return result; } no return value -(void)methodName:(id)args { //do something }tiConf.eu, valencia, 24/02/2013 33
  • 56. Proxy/Module Methods return value return value no args -(id)methodName:(id)args @Kroll.method { public String methodName() NSString result = @"Hello World”; { String result = "Hello world"; //do something //do something return result; } return result; } no return value -(void)methodName:(id)args { //do something }tiConf.eu, valencia, 24/02/2013 33
  • 57. Proxy/Module Methods return value return value no args -(id)methodName:(id)args @Kroll.method { public String methodName() NSString result = @"Hello World”; { String result = "Hello world"; //do something //do something return result; } return result; } no return value no return value @Kroll.method -(void)methodName:(id)args public void methodName(String value) { { //do something //do something } }tiConf.eu, valencia, 24/02/2013 33
  • 58. Example: xml2json module Expected API var xml2json = require(ti.xml2json); var json = xml2json.convert(xmlDoc); https://github.com/omorandi/TiXml2JsontiConf.eu, valencia, 24/02/2013 34
  • 59. Implementation @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]; } @endtiConf.eu, valencia, 24/02/2013 35
  • 60. Implementation @implementation TiXml2jsonModule -(NSDictionary) convertXml:(NSString)xmlString { NSDictionary *jsObj; //do conversion stuff return jsObj; } -(id)convert:(id)args NSArray of arguments { ENSURE_SINGLE_ARG(args, NSString); return [self convertXml:args]; } @endtiConf.eu, valencia, 24/02/2013 35
  • 61. Implementation @implementation TiXml2jsonModule -(NSDictionary) convertXml:(NSString)xmlString { NSDictionary *jsObj; //do conversion stuff return jsObj; } TiBase.h -(id)convert:(id)args NSArray of arguments #define ENSURE_SINGLE_ARG(x,t) { { ENSURE_SINGLE_ARG(args, NSString); x = (t*)[x objectAtIndex:0]; } return [self convertXml:args]; } @endtiConf.eu, valencia, 24/02/2013 35
  • 62. Utility Macros TiBase.h #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) ...tiConf.eu, valencia, 24/02/2013 36
  • 63. Types Supported Directly Conversion Utilities NSString NSDictionary #import "TiUtils.h" NSArray CGFloat f = [TiUtils floatValue:arg]; NSInteger f = [TiUtils intValue:arg]; NSNumber NSString *value = [TiUtils stringValue:arg]; NSDate TiColor *bgcolor = [TiUtils colorValue:arg]; NSNull UIColor *backgroundColor = [bgcolor color]; TiProxytiConf.eu, valencia, 24/02/2013 37
  • 64. Return Values • Single Value (NSString, NSNumber, …) • Collections (NSArray) ★ Converted into a JS Array object • Dictionary (NSDictionary) ★ Converted into a JS object ★ key->value ===> property->value • Proxy (TiProxy)tiConf.eu, valencia, 24/02/2013 38
  • 65. Return Values • Single Value (NSString, NSNumber, …) • Collections (NSArray) ★ Converted into a JS Array object • Dictionary (NSDictionary) ★ Converted into a JS object TS BJEC ★ key->value ===> property->value DO SE EA EL OR • Proxy (TiProxy) UR NA UT RETtiConf.eu, valencia, 24/02/2013 38
  • 66. xml2json Android import org.appcelerator.kroll.KrollDict; @Kroll.module(name="Tixml2json", id="ti.xml2json") public class Tixml2jsonModule extends KrollModule { @Kroll.method public KrollDict convert(String xml) { KrollDict json = null; //do conversion stuff return json; } }tiConf.eu, valencia, 24/02/2013 39
  • 67. xml2json Android import org.appcelerator.kroll.KrollDict; @Kroll.module(name="Tixml2json", id="ti.xml2json") public class Tixml2jsonModule extends KrollModule { KrollDict.java @Kroll.method public class KrollDict extends HashMap<String, Object> public KrollDict convert(String xml) { KrollDict json = null; //do conversion stuff return json; } }tiConf.eu, valencia, 24/02/2013 39
  • 68. Types Supported Directly Conversion UtilitiesStringint import org.appcelerator.titanium.util.TiConvert;float int val = TiConvert.toInt(obj);double float val = TiConvert.toFloat(obj);boolean double val = TiConvert.toDouble(obj); boolean val = TiConvert.toBoolean(obj);Object[] int color = TiConvert.toColor(str);HashMap<String, Object> ...TiProxy http://builds.appcelerator.com.s3.amazonaws.com/module-apidoc/2.0.0/android/org/appcelerator/titanium/util/TiConvert.htmltiConf.eu, valencia, 24/02/2013 40
  • 69. Return Values • Single Value (String, Integer, …) • Collections (Object[]) ★ Converted into a JS Array object • Dictionary (HashMap<String, Object>) ★ Converted into a JS object ★ key->value ===> property->value • Proxy (TiProxy)tiConf.eu, valencia, 24/02/2013 41
  • 70. Polymorphic Methods -(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]; } }tiConf.eu, valencia, 24/02/2013 42
  • 71. Polymorphic Methods public KrollDict convertFromString(String xml); public KrollDict convertFromBlob(TiBlob blob) @Kroll.method public 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"); }tiConf.eu, valencia, 24/02/2013 43
  • 72. Varargs -(void) varArgsMethod:(id)args { for (int i = 0; i < [args count]; i++) { id arg = [args objectAtIndex:i]; // do something with arg } }tiConf.eu, valencia, 24/02/2013 44
  • 73. Varargs @Kroll.method public void varArgsMethod(Object[] args) { for (int i = 0; i < args.length; i++) { Object arg = args[i]; // do something with arg } }tiConf.eu, valencia, 24/02/2013 45
  • 74. Properties set module.propertyName = "HELLO"; get Ti.API.info("Property: " + module.propertyName);tiConf.eu, valencia, 24/02/2013 46
  • 75. Properties TiMyModule.h @interface TiMyModule: TiModule @property (nonatomic, readwrite, retain) NSString* propertyName; @end TiMyModule.m @implementation TiMyModule: TiModule @synthesize propertyName; @endtiConf.eu, valencia, 24/02/2013 47
  • 76. Properties: Setter/Getter - (void) setPropertyName:(id)args { // set property and do stuff } - (id) propertyName { // do something and return value; }tiConf.eu, valencia, 24/02/2013 48
  • 77. Properties: Setter/Getter @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; } }tiConf.eu, valencia, 24/02/2013 49
  • 78. Constants 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); }tiConf.eu, valencia, 24/02/2013 50
  • 79. Constants https://github.com/omorandi/TiSMSDialog/blob/master/Classes/ComOmorandiSMSDialogProxy.m //create the accessor methods for the SENT, CANCELLED and FAILED constants MAKE_SYSTEM_PROP(SENT,MessageComposeResultSent); MAKE_SYSTEM_PROP(CANCELLED,MessageComposeResultCancelled); MAKE_SYSTEM_PROP(FAILED,MessageComposeResultFailed);tiConf.eu, valencia, 24/02/2013 51
  • 80. Constants https://github.com/omorandi/TiSMSDialog/blob/master/Classes/ComOmorandiSMSDialogProxy.m //create the accessor methods for the SENT, CANCELLED and FAILED constants MAKE_SYSTEM_PROP(SENT,MessageComposeResultSent); MAKE_SYSTEM_PROP(CANCELLED,MessageComposeResultCancelled); MAKE_SYSTEM_PROP(FAILED,MessageComposeResultFailed);TiBase.h#define MAKE_SYSTEM_PROP(name,map) -(NSNumber*)name {return [NSNumber numberWithInt:map];}tiConf.eu, valencia, 24/02/2013 51
  • 81. Constants https://github.com/omorandi/TiSMSDialog/blob/master/Classes/ComOmorandiSMSDialogProxy.m //create the accessor methods for the SENT, CANCELLED and FAILED constants MAKE_SYSTEM_PROP(SENT,MessageComposeResultSent); MAKE_SYSTEM_PROP(CANCELLED,MessageComposeResultCancelled); MAKE_SYSTEM_PROP(FAILED,MessageComposeResultFailed);TiBase.h#define MAKE_SYSTEM_PROP(name,map) -(NSNumber*)name {return [NSNumber numberWithInt:map];} @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; }tiConf.eu, valencia, 24/02/2013 51
  • 82. Proxy Objects var smsModule = require(ti.ios.sms); //create the smsDialog object var smsDialog = smsModule.createSMSDialog({ recipients: [+123456789], messageBody: hello }); smsDialog.open();tiConf.eu, valencia, 24/02/2013 52
  • 83. Creating a Proxy TiIosSmsSMSDialogProxy.h @interface TiIosSmsSMSDialogProxy: TiProxy<MFMessageComposeViewControllerDelegate> @end TiIosSmsSMSDialogProxy.m @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 } @endtiConf.eu, valencia, 24/02/2013 53
  • 84. Proxy Objects var smsModule = require(ti.android.sms); //create the sms object var sms = smsModule.createSms({ recipient: +123456789, messageBody: hello }); sms.send();tiConf.eu, valencia, 24/02/2013 54
  • 85. Creating a Proxy @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 } }tiConf.eu, valencia, 24/02/2013 55
  • 86. Events Notify a change of state, or an asynchronous event // create the Module object var tibarcode = require(ti.barcode); var scanner = tibarcode.createScanner(); // success event listener scanner.addEventListener(success, function(e) { var code = e.barcode; var type = e.type; alert(Found code: + code + type: + type); });tiConf.eu, valencia, 24/02/2013 56
  • 87. Events @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]; } } @endtiConf.eu, valencia, 24/02/2013 57
  • 88. Events 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); } } }tiConf.eu, valencia, 24/02/2013 58
  • 89. Callbacks Notify the result of an asynchronous action // lets not freeze on huge xml data xml2json.convertAsync(xmlDoc, function(data) { Ti.API.info("JSON object: " + JSON.stringify(data.json)); });tiConf.eu, valencia, 24/02/2013 59
  • 90. Callbacks -(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]; }); }tiConf.eu, valencia, 24/02/2013 60
  • 91. Callbacks @Kroll.method public 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(); }tiConf.eu, valencia, 24/02/2013 61
  • 92. ViewProxy Manages the Holds the state native view of a view hierarchy Methods Native Views ViewProxy Hierarchy Properties View (get/set) EventstiConf.eu, valencia, 24/02/2013 62
  • 93. ViewProxy Manages the Holds the state native view of a view hierarchy Methods Native Views ViewProxy Hierarchy Properties View (get/set) Events JS THREADtiConf.eu, valencia, 24/02/2013 62
  • 94. ViewProxy Manages the Holds the state native view of a view hierarchy Methods Native Views ViewProxy Hierarchy Properties View (get/set) Events JS THREAD UI THREADtiConf.eu, valencia, 24/02/2013 62
  • 95. ViewProxy Manages the Holds the state native view of a view hierarchy Methods Native Views ViewProxy Hierarchy Properties View (get/set) Events JS THREAD UI THREAD Mostly asynctiConf.eu, valencia, 24/02/2013 62
  • 96. Super-Smooth TableView• API • createMessagesView(properties); • setMessages([]messages); • insert(message); • addEventListener(‘click’, callback);tiConf.eu, valencia, 24/02/2013 63
  • 97. Implementation MessagesViewProxy TiSmoothMessagesViewProxy.h @interface TiSmoothMessagesViewProxy : TiViewProxy @property (nonatomic, retain) MessagesCollection *msgs; //model @end TiSmoothMessagesViewProxy.m @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]; } @endtiConf.eu, valencia, 24/02/2013 64
  • 98. Implementation MessagesViewProxy TiSmoothMessagesViewProxy.h @interface TiSmoothMessagesViewProxy : TiViewProxy @property (nonatomic, retain) MessagesCollection *msgs; //model @end TiSmoothMessagesViewProxy.m @implementation TiSmoothMessagesViewProxy @synthesize msgs; //other methods -(void) insert:(id)args { ENSURE_SINGLE_ARG(args, NSDictionary); [self.msgs insertMessageOnTop:[self messageFromDictionary:(NSDictionary*)args]]; create the view and call addMessage on the UI thread [self makeViewPerformSelector:@selector(addMessage:) withObject:args createIfNeeded:YES waitUntilDone:NO]; } @endtiConf.eu, valencia, 24/02/2013 64
  • 99. Implementation MessagesView TiSmoothMessagesView.h @interface TiSmoothMessagesView : TiUIView { MessagesViewController *viewController; } @end TiSmoothMessagesView.m @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]; } @endtiConf.eu, valencia, 24/02/2013 65
  • 100. Implementation MessagesView TiSmoothMessagesView.h @interface TiSmoothMessagesView : TiUIView { MessagesViewController *viewController; } @end TiSmoothMessagesView.m @implementation TiSmoothMessagesView -(void)initializeState called by Titanium at view creation { [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]; } @endtiConf.eu, valencia, 24/02/2013 65
  • 101. Implementation MessagesView TiSmoothMessagesView.h @interface TiSmoothMessagesView : TiUIView { MessagesViewController *viewController; } @end TiSmoothMessagesView.m @implementation TiSmoothMessagesView -(void)initializeState called by Titanium at view creation { [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 called by Titanium for notifying a { change in frame size [TiUtils setView: viewController.tableView positionRect:bounds]; } @endtiConf.eu, valencia, 24/02/2013 65
  • 102. module.xcconfig // // 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 build & package Module Package (.zip) app bundletiConf.eu, valencia, 24/02/2013 66
  • 103. module.xcconfig // // 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 build & package Module Package (.zip) app bundletiConf.eu, valencia, 24/02/2013 66
  • 104. timodule.xml <?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> build & package AndroidManifest.xml Module Package (.zip) app.apktiConf.eu, valencia, 24/02/2013 67
  • 105. DebuggingtiConf.eu, valencia, 24/02/2013
  • 106. Create a debug build $ sed s/Release/Debug/ build.py > build_debug.py build.py 168: rc = os.system("xcodebuild -sdk iphoneos -configuration Release") 171: rc = os.system("xcodebuild -sdk iphonesimulator -configuration Release") build_debug.py 168: rc = os.system("xcodebuild -sdk iphoneos -configuration Debug") 171: rc = os.system("xcodebuild -sdk iphonesimulator -configuration Debug")tiConf.eu, valencia, 24/02/2013 69
  • 107. DebuggingtiConf.eu, valencia, 24/02/2013 70
  • 108. Debug Logs @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"); } }tiConf.eu, valencia, 24/02/2013 71
  • 109. Android DDMStiConf.eu, valencia, 24/02/2013 72
  • 110. Thank you!tiConf.eu, valencia, 24/02/2013

×