際際滷

際際滷Share a Scribd company logo
TICONFEU,AMSTERDAM,29/06/2014
{native: FTW}
!
Integrating native views in Titanium apps
Olivier Morandi
TICONFEU,AMSTERDAM,29/06/2014
Olivier Morandi
Software engineer
!
http://titaniumninja.com!
olivier.morandi@gmail.com
@olivier_morandi
https://github.com/omorandi
2
TICONFEU,AMSTERDAM,29/06/2014 3
TICONFEU,AMSTERDAM,29/06/2014
 Ti app development
 Native module development (iOS/Android)
 Optimisations
 R&D
4
TICONFEU,AMSTERDAM,29/06/2014
This Talk
 How to create view-based native modules
 How to integrate third party libraries
5
TICONFEU,AMSTERDAM,29/06/2014
Not in This Talk
 Basics of native module development
 module creation
 proxies, methods, properties, events,
callbacks
 Check out http://www.slideshare.net/
omorandi/ticonf
6
TICONFEU,AMSTERDAM,29/06/2014
Why Native Views
 UX/Performance
 Stock Ti UI components not suitable for
the speci鍖c UX requirements
 Integration of native UI components and
libraries
 Leverage existing solutions from the
Android and iOS OSS communities
 Integrate third party SDKs
7
TICONFEU,AMSTERDAM,29/06/2014
Ti.Next/Hyperloop
 Q: Are Ti.Current native modules still
relevant?
 A: YES!
 Ti.Next/Hyperloop is WIP
 Active need in current Titanium projects
 Maintaining legacy modules
8
TICONFEU,AMSTERDAM,29/06/2014
Learning Resources
TICONFEU,AMSTERDAM,29/06/2014
O鍖cial 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_Guide
10
TICONFEU,AMSTERDAM,29/06/2014 11
TICONFEU,AMSTERDAM,29/06/2014
Source code
 Titanium Mobile SDK
 https://github.com/appcelerator/
titanium_mobile
 Open source modules from Appcelerator
 https://github.com/appcelerator/
titanium_modules
12
TICONFEU,AMSTERDAM,29/06/2014
Follow these people (and more)
 Aaron K. Saunders: https://github.com/aaronksaunders
 Adam Paxton: https://github.com/adampax/
 Ben Bahrenburg: https://github.com/benbahrenburg
 David Bankier: https://github.com/dbankier
 Jordi Domenec: https://github.com/iamyellow
 Mads M淡ller: https://github.com/viezel
 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
 Many more 鍖nd them on http://gitt.io/
13
TICONFEU,AMSTERDAM,29/06/2014
Architecture Recap
TICONFEU,AMSTERDAM,29/06/2014 15
Titanium cli (node.js)
TICONFEU,AMSTERDAM,29/06/2014
Runtime (iOS)
16
Titanium
Modules
(API)
JS APP
Parser
Interpreter
IOS SDK
Bytecode
gen
JavaScriptCore
objective-c
C++
KROLLBRIDGE
TICONFEU,AMSTERDAM,29/06/2014
Runtime (iOS)
16
Titanium
Modules
(API)
JS APP
Parser
Interpreter
IOS SDK
Bytecode
gen
JavaScriptCore
NO JIT
objective-c
C++
KROLLBRIDGE
TICONFEU,AMSTERDAM,29/06/2014
Titanium
Modules
(API)
JS APP
Parser
Native Code
Android SDK
Native Code
gen
KROLLBRIDGE
Runtime (Android)
17
Java
C++
V8
OPT
TICONFEU,AMSTERDAM,29/06/2014
Titanium
Modules
(API)
JS APP
Parser
Native Code
Android SDK
Native Code
gen
KROLLBRIDGE
Runtime (Android)
17
Java
C++
V8
OPT
TICONFEU,AMSTERDAM,29/06/2014
Titanium
Modules
(API)
JS APP
Parser
Native Code
Android SDK
Native Code
gen
KROLLBRIDGE
Runtime (Android)
17
Java
C++
V8
OPT
TICONFEU,AMSTERDAM,29/06/2014
Terminology
18
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();
TICONFEU,AMSTERDAM,29/06/2014
Terminology
18
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();
module
object
TICONFEU,AMSTERDAM,29/06/2014
Terminology
18
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();
factory
method
TICONFEU,AMSTERDAM,29/06/2014
Terminology
18
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
TICONFEU,AMSTERDAM,29/06/2014
Terminology
18
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
object
TICONFEU,AMSTERDAM,29/06/2014
Terminology
18
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 proxy
object
TICONFEU,AMSTERDAM,29/06/2014
Terminology
18
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
TICONFEU,AMSTERDAM,29/06/2014
Terminology
18
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
TICONFEU,AMSTERDAM,29/06/2014
Proxies & Modules
Proxy
ViewProxy ViewModule
extends
has a
creates
19
manages
NativeView Type	

iOS UIView	

AndroidView
extends
TICONFEU,AMSTERDAM,29/06/2014
Proxies & Modules
Proxy
ViewProxy ViewModule
extends
has a
creates
19
manages
NativeView Type	

iOS UIView	

AndroidView
State:
properties
Actions:
methods
Events:
addEventListener(), fireEvent()
Interface
extends
TICONFEU,AMSTERDAM,29/06/2014
Proxies & Modules
Proxy
ViewProxy ViewModule
extends
has a
creates
19
manages
NativeView Type	

iOS UIView	

AndroidView
State:
properties
Actions:
methods
Events:
addEventListener(), fireEvent()
Interface
Methods for the integration within the
application lifecycle
startup() (iOS)
shutdown() (iOS)
onAppCreate() (Android)
extends
TICONFEU,AMSTERDAM,29/06/2014
Proxies & Modules
Proxy
ViewProxy ViewModule
extends
has a
creates
19
manages
NativeView Type	

iOS UIView	

AndroidView
State:
properties
Actions:
methods
Events:
addEventListener(), fireEvent()
Interface
Additional members for the integration
within the UI layout system:
add()
remove()
height
width
backgroundColor
...
Methods for the integration within the
application lifecycle
startup() (iOS)
shutdown() (iOS)
onAppCreate() (Android)
extends
TICONFEU,AMSTERDAM,29/06/2014
ViewProxy
20
ViewProxy
View
NativeViews
Hierarchy
Methods
Properties
(get/set)
Events
Holds the state
of a view
Manages the
native view
hierarchy
TICONFEU,AMSTERDAM,29/06/2014
ViewProxy
20
ViewProxy
View
NativeViews
Hierarchy
Methods
Properties
(get/set)
Events
Holds the state
of a view
Manages the
native view
hierarchy
JS THREAD
TICONFEU,AMSTERDAM,29/06/2014
ViewProxy
20
ViewProxy
View
NativeViews
Hierarchy
Methods
Properties
(get/set)
Events
Holds the state
of a view
Manages the
native view
hierarchy
JS THREAD UI THREAD
TICONFEU,AMSTERDAM,29/06/2014
ViewProxy
20
ViewProxy
View
NativeViews
Hierarchy
Methods
Properties
(get/set)
Events
Holds the state
of a view
Manages the
native view
hierarchy
JS THREAD UI THREAD
ASYNC
TICONFEU,AMSTERDAM,29/06/2014
A Basic Native View
TICONFEU,AMSTERDAM,29/06/2014 22
TICONFEU,AMSTERDAM,29/06/2014
Usage Scenario
23
var win = Ti.UI.createWindow({
backgroundColor: 'white'
});
!
var ticonf = require('ti.conf');
!
var basicView = ticonf.createBasicView({
width: 100,
height: 100
});
!
win.add(basicView);
!
win.open();
app.js
TICONFEU,AMSTERDAM,29/06/2014
ViewProxy Class
24
#import "TiViewProxy.h"
!
@interface TiConfBasicViewProxy : TiViewProxy
@end
TiConfBasicViewProxy.h
TiConfBasicViewProxy.m
#import "TiConfBasicViewProxy.h"
!
@implementation TiConfBasicViewProxy
!
!
@end
TICONFEU,AMSTERDAM,29/06/2014
View Class
25
#import "TiUIView.h"
!
@interface TiConfBasicView : TiUIView
{
UIView *theView;
}
@end
TiConfBasicView.h
TiConfBasicView.m
#import "TiConfBasicView.h"
!
@implementation TiConfBasicView
!
-(void)initializeState
{
theView = [[UIView alloc] initWithFrame:self.bounds];
theView.backgroundColor = [UIColor redColor];
[self addSubview:theView];
}
!
@end
TICONFEU,AMSTERDAM,29/06/2014 26
TICONFEU,AMSTERDAM,29/06/2014 26
WTF: wheres my view?
TICONFEU,AMSTERDAM,29/06/2014 26
WTF: wheres my view?
TiConfBasicView
TICONFEU,AMSTERDAM,29/06/2014 26
WTF: wheres my view?
TiConfBasicView
theView
TICONFEU,AMSTERDAM,29/06/2014
Managing the subview frame
27
TiConfBasicView.m
#import "TiConfBasicView.h"
!
@implementation TiConfBasicView
!
!
-(void)initializeState
{
theView = [[UIView alloc] initWithFrame:self.bounds];
theView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
theView.backgroundColor = [UIColor redColor];
[self addSubview:theView];
}
!
@end
TICONFEU,AMSTERDAM,29/06/2014
Managing the subview frame
27
TiConfBasicView.m
#import "TiConfBasicView.h"
!
@implementation TiConfBasicView
!
!
-(void)initializeState
{
theView = [[UIView alloc] initWithFrame:self.bounds];
theView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
theView.backgroundColor = [UIColor redColor];
[self addSubview:theView];
}
!
@end
The Ti View frame is managed by the Ti
layout system.
Bounds are not valid until the view takes
part to an on-screen Ti view hierarchy
TICONFEU,AMSTERDAM,29/06/2014
Managing the subview frame
27
TiConfBasicView.m
#import "TiConfBasicView.h"
!
@implementation TiConfBasicView
!
!
-(void)initializeState
{
theView = [[UIView alloc] initWithFrame:self.bounds];
theView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
theView.backgroundColor = [UIColor redColor];
[self addSubview:theView];
}
!
@end
The Ti View frame is managed by the Ti
layout system.
Bounds are not valid until the view takes
part to an on-screen Ti view hierarchy
TICONFEU,AMSTERDAM,29/06/2014
An alternative
28
TiConfBasicView.m
-(void)initializeState
{
theView = [[UIView alloc] initWithFrame:self.bounds];
theView.backgroundColor = [UIColor redColor];
[self addSubview:theView];
}
!
!
!
-(void)frameSizeChanged:(CGRect)frame bounds:(CGRect)bounds
{
theView.frame = bounds;
}
TICONFEU,AMSTERDAM,29/06/2014
An alternative
28
TiConfBasicView.m
-(void)initializeState
{
theView = [[UIView alloc] initWithFrame:self.bounds];
theView.backgroundColor = [UIColor redColor];
[self addSubview:theView];
}
!
!
!
-(void)frameSizeChanged:(CGRect)frame bounds:(CGRect)bounds
{
theView.frame = bounds;
}
called by -[TiUIView drawRect:]
TICONFEU,AMSTERDAM,29/06/2014
ViewProxy Class
29
@Kroll.proxy(creatableInModule=AndroidModule.class)
public class BasicViewProxy extends TiViewProxy
{
// Constructor
public BasicViewProxy()
{
super();
}
!
@Override
public TiUIView createView(Activity activity)
{
TiUIView view = new BasicView(this);
return view;
}
!
}
BasicViewProxy.java
TICONFEU,AMSTERDAM,29/06/2014
View Class
30
public class BasicView extends TiUIView
{
View theView;
public BasicView(TiViewProxy proxy) {
super(proxy);
!
Activity context = proxy.getActivity();
theView = new View(context);
theView.setBackgroundColor(Color.RED);
getLayoutParams().autoFillsHeight = true;
getLayoutParams().autoFillsWidth = true;
setNativeView(theView);
}
!
}
BasicView.java
TICONFEU,AMSTERDAM,29/06/2014 31
TICONFEU,AMSTERDAM,29/06/2014
Properties
 Properties belong to the ViewProxy object
 How do we make use of property values in
View objects?
32
TICONFEU,AMSTERDAM,29/06/2014
Setting a property
33
var basicView = ticonf.createBasicView({
color: "red"
});
!
//or
!
basicView.color = "red";
TICONFEU,AMSTERDAM,29/06/2014
Property from the Proxy
34
!
UIColor *color = [[TiUtils colorValue:[self.proxy valueForKey:@"color"]] color];
TiConfBasicView.m
Retrieving the property value from the ViewProxy when needed
TICONFEU,AMSTERDAM,29/06/2014
Explicit Setter in the ViewProxy
35
-(void)setColor:(UIColor*)color
{
theView.backgroundColor = color;
}
TiConfBasicView.m
-(void)setColor:(id)args
{
//expect 1 argument
ENSURE_ARG_COUNT(args, 1);
UIColor *color = [[TiUtils colorValue:args] color];
//dispatch to the view on UI thread
//(create it if needed, don't wait for completion)
[self makeViewPerformSelector:@selector(setColor:)
withObject:color createIfNeeded:YES waitUntilDone:NO];
}
TiConfBasicViewProxy.m
TICONFEU,AMSTERDAM,29/06/2014
Explicit Setter in the ViewProxy
35
-(void)setColor:(UIColor*)color
{
theView.backgroundColor = color;
}
TiConfBasicView.m
-(void)setColor:(id)args
{
//expect 1 argument
ENSURE_ARG_COUNT(args, 1);
UIColor *color = [[TiUtils colorValue:args] color];
//dispatch to the view on UI thread
//(create it if needed, don't wait for completion)
[self makeViewPerformSelector:@selector(setColor:)
withObject:color createIfNeeded:YES waitUntilDone:NO];
}
TiConfBasicViewProxy.m
JS
THREAD
TICONFEU,AMSTERDAM,29/06/2014
Explicit Setter in the ViewProxy
35
-(void)setColor:(UIColor*)color
{
theView.backgroundColor = color;
}
TiConfBasicView.m
-(void)setColor:(id)args
{
//expect 1 argument
ENSURE_ARG_COUNT(args, 1);
UIColor *color = [[TiUtils colorValue:args] color];
//dispatch to the view on UI thread
//(create it if needed, don't wait for completion)
[self makeViewPerformSelector:@selector(setColor:)
withObject:color createIfNeeded:YES waitUntilDone:NO];
}
TiConfBasicViewProxy.m
JS
THREAD
UI
THREAD
TICONFEU,AMSTERDAM,29/06/2014
Implicit Setter in the View Class
36
-(void)setColor_:(id)arg
{
theView.backgroundColor = [[TiUtils colorValue:arg] color];
}
TiConfBasicView.m
TICONFEU,AMSTERDAM,29/06/2014
Implicit Setter in the View Class
36
-(void)setColor_:(id)arg
{
theView.backgroundColor = [[TiUtils colorValue:arg] color];
}
TiConfBasicView.m
Automatically dispatched by the
ViewProxy on the UI thread
TICONFEU,AMSTERDAM,29/06/2014
Property from the Proxy
37
!
int color = TiConvert.toColor((String) proxy.getProperty(color"));
BasicView.java
TICONFEU,AMSTERDAM,29/06/2014
Creation Properties
38
BasicView.java
@Override
public void processProperties(KrollDict props)
{
super.processProperties(props);
if (props.containsKey("color")) {
theView.setBackgroundColor(TiConvert.toColor(props.getString("color")));
}
else if () {
//do something else
}
}
TICONFEU,AMSTERDAM,29/06/2014
Property Changed Listener
39
BasicView.java
@Override
public void propertyChanged(String key, Object oldValue, Object newValue, KrollProxy proxy)
{
if (key.equals("color")) {
theView.setBackgroundColor(TiConvert.toColor((String)newValue));
} else if () {
//do something else
}
}
public abstract class TiUIView implements KrollProxyListener
titanium_mobile/android/titanium/src/java/org/appcelerator/titanium/view/TiUIView.java:73
TICONFEU,AMSTERDAM,29/06/2014
Methods
 Exposed to JS by the ViewProxy object
 Dispatched to the View object
40
TICONFEU,AMSTERDAM,29/06/2014
View Methods
41
basicView.makeRounded();
TICONFEU,AMSTERDAM,29/06/2014 42
TICONFEU,AMSTERDAM,29/06/2014
View Method
43
-(void)makeRounded
{
theView.layer.cornerRadius = 20;
}
TiConfBasicView.m
-(void)makeRounded:(id)args
{
ENSURE_UI_THREAD(makeRounded, args);
TiConfBasicView *thisView = (TiConfBasicView*)[self view];
[thisView makeRounded];
}
TiConfBasicViewProxy.m
TICONFEU,AMSTERDAM,29/06/2014
View Method
43
-(void)makeRounded
{
theView.layer.cornerRadius = 20;
}
TiConfBasicView.m
-(void)makeRounded:(id)args
{
ENSURE_UI_THREAD(makeRounded, args);
TiConfBasicView *thisView = (TiConfBasicView*)[self view];
[thisView makeRounded];
}
TiConfBasicViewProxy.m
JS
THREAD
TICONFEU,AMSTERDAM,29/06/2014
View Method
43
-(void)makeRounded
{
theView.layer.cornerRadius = 20;
}
TiConfBasicView.m
-(void)makeRounded:(id)args
{
ENSURE_UI_THREAD(makeRounded, args);
TiConfBasicView *thisView = (TiConfBasicView*)[self view];
[thisView makeRounded];
}
TiConfBasicViewProxy.m
JS
THREAD
UI
THREAD
TICONFEU,AMSTERDAM,29/06/2014
Dispatching via GCD
44
-(void)makeRounded
{
theView.layer.cornerRadius = 20;
}
TiConfBasicView.m
-(void)makeRounded:(id)args
{
dispatch_async(dispatch_get_main_queue(), ^{
TiConfBasicView *thisView = (TiConfBasicView*)[self view];
[thisView makeRounded];
});
}
TiConfBasicViewProxy.m
TICONFEU,AMSTERDAM,29/06/2014
View Method Dispatching
45
public void makeRounded() {
GradientDrawable shape = new GradientDrawable();
shape.setColor(Color.RED);
shape.setCornerRadius(50);
theView.setBackgroundDrawable(shape);
}
BasicView.java
@Kroll.method
public void makeRounded() {
TiMessenger.postOnMain(new Runnable() {
!
@Override
public void run() {
BasicView view = (BasicView)getOrCreateView();
view.makeRounded();
}
});
}
BasicViewProxy.java
TICONFEU,AMSTERDAM,29/06/2014
View Method Dispatching
45
public void makeRounded() {
GradientDrawable shape = new GradientDrawable();
shape.setColor(Color.RED);
shape.setCornerRadius(50);
theView.setBackgroundDrawable(shape);
}
BasicView.java
@Kroll.method
public void makeRounded() {
TiMessenger.postOnMain(new Runnable() {
!
@Override
public void run() {
BasicView view = (BasicView)getOrCreateView();
view.makeRounded();
}
});
}
BasicViewProxy.java
JS
THREAD
TICONFEU,AMSTERDAM,29/06/2014
View Method Dispatching
45
public void makeRounded() {
GradientDrawable shape = new GradientDrawable();
shape.setColor(Color.RED);
shape.setCornerRadius(50);
theView.setBackgroundDrawable(shape);
}
BasicView.java
@Kroll.method
public void makeRounded() {
TiMessenger.postOnMain(new Runnable() {
!
@Override
public void run() {
BasicView view = (BasicView)getOrCreateView();
view.makeRounded();
}
});
}
BasicViewProxy.java
JS
THREAD
UI
THREAD
TICONFEU,AMSTERDAM,29/06/2014
Message Dispatching
46
private static final int MSG_MAKE_ROUNDED = TiViewProxy.MSG_LAST_ID + 4001;
protected static final int MSG_LAST_ID = MSG_MAKE_ROUNDED;
!
private void handleMakeRounded() {
BasicView view = (BasicView)getOrCreateView();
view.makeRounded();
}
@Override
public boolean handleMessage(Message msg){
if (msg.what == MSG_MAKE_ROUNDED) {
handleMakeRounded();
return true;
}
return super.handleMessage(msg);
}
@Kroll.method
public void makeRounded() {
if (TiApplication.isUIThread()) {
handleMakeRounded();
} else {
TiMessenger.sendBlockingMainMessage(getMainHandler().obtainMessage(MSG_MAKE_ROUNDED));
}
}
BasicViewProxy.java
TICONFEU,AMSTERDAM,29/06/2014
View Events
47
basicView.addEventListener('viewTapped', function() {
alert('tapped');
});
TICONFEU,AMSTERDAM,29/06/2014
Firing Events
48
-(void)initializeState
{
theView = [[UIView alloc] initWithFrame:self.bounds];
// other initialisation operations
!
UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc]
initWithTarget:self action:@selector(basicViewTapped:)];
// Specify that the gesture must be a single tap
tapRecognizer.numberOfTapsRequired = 1;
// Add the tap gesture recognizer to the view
[theView addGestureRecognizer:tapRecognizer];
}
!
- (void)basicViewTapped:(UITapGestureRecognizer *)recognizer {
NSDictionary *event = @{@"color": @"red"};
[self.proxy fireEvent:@"viewTapped" withObject:event];
}
TiConfBasicView.m
TICONFEU,AMSTERDAM,29/06/2014
Firing Events
48
-(void)initializeState
{
theView = [[UIView alloc] initWithFrame:self.bounds];
// other initialisation operations
!
UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc]
initWithTarget:self action:@selector(basicViewTapped:)];
// Specify that the gesture must be a single tap
tapRecognizer.numberOfTapsRequired = 1;
// Add the tap gesture recognizer to the view
[theView addGestureRecognizer:tapRecognizer];
}
!
- (void)basicViewTapped:(UITapGestureRecognizer *)recognizer {
NSDictionary *event = @{@"color": @"red"};
[self.proxy fireEvent:@"viewTapped" withObject:event];
}
TiConfBasicView.m
TICONFEU,AMSTERDAM,29/06/2014
Firing Events
49
public BasicView(final TiViewProxy proxy) {
super(proxy);
!
Activity context = proxy.getActivity();
theView = new View(context);
!
//other initialisation operations
View.OnTouchListener gestureListener = new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent e) {
KrollDict event = new KrollDict();
event.put("color", "red");
proxy.fireEvent("viewTapped", event);
return true;
}
};
theView.setOnTouchListener(gestureListener);
!
setNativeView(theView);
}
BasicView.java
TICONFEU,AMSTERDAM,29/06/2014
Firing Events
49
public BasicView(final TiViewProxy proxy) {
super(proxy);
!
Activity context = proxy.getActivity();
theView = new View(context);
!
//other initialisation operations
View.OnTouchListener gestureListener = new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent e) {
KrollDict event = new KrollDict();
event.put("color", "red");
proxy.fireEvent("viewTapped", event);
return true;
}
};
theView.setOnTouchListener(gestureListener);
!
setNativeView(theView);
}
BasicView.java
TICONFEU,AMSTERDAM,29/06/2014
Integrating Third
Party Libraries
TICONFEU,AMSTERDAM,29/06/2014
iOS Static Library
 Static library 鍖le (.a)
 Objective-c/C/C++ headers folder
51
TICONFEU,AMSTERDAM,29/06/2014
iOS Static Library
52
TICONFEU,AMSTERDAM,29/06/2014
iOS Static Library
52
includes (headers) folder
TICONFEU,AMSTERDAM,29/06/2014
iOS Static Library
52
includes (headers) folder
static lib 鍖le (.a)
TICONFEU,AMSTERDAM,29/06/2014
iOS Static Library
52
includes (headers) folder
static lib 鍖le (.a)
ensure the lib is linked
with the module
TICONFEU,AMSTERDAM,29/06/2014
iOS Frameworks
 Framework bundle
 Header 鍖les
 Library
 Resources
53
TICONFEU,AMSTERDAM,29/06/2014
iOS Frameworks
54
TITANIUM_SDK_VERSION = 3.2.3.GA
!
!
TITANIUM_SDK = ~/Library/Application Support/Titanium/mobilesdk/osx/$(TITANIUM_SDK_VERSION)
TITANIUM_BASE_SDK = "$(TITANIUM_SDK)/iphone/include"
TITANIUM_BASE_SDK2 = "$(TITANIUM_SDK)/iphone/include/TiCore"
HEADER_SEARCH_PATHS= $(TITANIUM_BASE_SDK) $(TITANIUM_BASE_SDK2) /PATH/TO/YOUR/FRAMEWORK/HEADERS
titanium.xccon鍖g
TICONFEU,AMSTERDAM,29/06/2014
iOS Frameworks
54
TITANIUM_SDK_VERSION = 3.2.3.GA
!
!
TITANIUM_SDK = ~/Library/Application Support/Titanium/mobilesdk/osx/$(TITANIUM_SDK_VERSION)
TITANIUM_BASE_SDK = "$(TITANIUM_SDK)/iphone/include"
TITANIUM_BASE_SDK2 = "$(TITANIUM_SDK)/iphone/include/TiCore"
HEADER_SEARCH_PATHS= $(TITANIUM_BASE_SDK) $(TITANIUM_BASE_SDK2) /PATH/TO/YOUR/FRAMEWORK/HEADERS
titanium.xccon鍖g
TICONFEU,AMSTERDAM,29/06/2014
iOS Frameworks
54
TITANIUM_SDK_VERSION = 3.2.3.GA
!
!
TITANIUM_SDK = ~/Library/Application Support/Titanium/mobilesdk/osx/$(TITANIUM_SDK_VERSION)
TITANIUM_BASE_SDK = "$(TITANIUM_SDK)/iphone/include"
TITANIUM_BASE_SDK2 = "$(TITANIUM_SDK)/iphone/include/TiCore"
HEADER_SEARCH_PATHS= $(TITANIUM_BASE_SDK) $(TITANIUM_BASE_SDK2) /PATH/TO/YOUR/FRAMEWORK/HEADERS
titanium.xccon鍖g
Used ad module build time
TICONFEU,AMSTERDAM,29/06/2014
iOS Frameworks
55
!
OTHER_LDFLAGS=$(inherited) -framework <FRAMEWORK> -F <PATH/TO/FRAMEWORK>
!
For example:
!
OTHER_LDFLAGS=$(inherited) -framework ArcGIS -F $HOME/Library/SDKs/ArcGIS/iOS/
module.xccon鍖g
TICONFEU,AMSTERDAM,29/06/2014
iOS Frameworks
55
!
OTHER_LDFLAGS=$(inherited) -framework <FRAMEWORK> -F <PATH/TO/FRAMEWORK>
!
For example:
!
OTHER_LDFLAGS=$(inherited) -framework ArcGIS -F $HOME/Library/SDKs/ArcGIS/iOS/
module.xccon鍖g
Used ad application build time
TICONFEU,AMSTERDAM,29/06/2014
ARC vs. NON-ARC
 ARC = Automatic Reference Counting
 Retain/Release handled automatically by
the Clang compiler
 Ti module template project is still NON-
ARC
 You can use ARC code inside of a Ti
module project
56
TICONFEU,AMSTERDAM,29/06/2014
Enabling ARC for a speci鍖c 鍖le
57
TICONFEU,AMSTERDAM,29/06/2014
Using external JARs
58
drag & drop the JAR in the
lib folder of the module
project
TICONFEU,AMSTERDAM,29/06/2014
Using external JARs
59
Add the external JAR
to the project build
path
TICONFEU,AMSTERDAM,29/06/2014
Integrating native libs (NDK)
60
Import the native shared
libraries (.so), separated
by target architecture in
the lib folder
TICONFEU,AMSTERDAM,29/06/2014
Fix build.xml
61
<project name="android" default="dist">	
	 <description>	
	 	 Ant build script for Titanium Android module android	
	 </description>	
!
	 <property name="ti.module.root" location="${basedir}"/>	
	 <property file="build.properties" />	
!
	 <import file="${titanium.platform}/../module/android/build.xml"/>	
	 	
	 <target name="post.jar">	
	 	 <copy todir="${libs}">	
	 <fileset dir="lib">	
		 <include name="**/*.so"/>	
	 </fileset>	
		 </copy>	
	 </target>	
</project>	
build.xml
Copy the .so 鍖les from lib to
libs before packaging
Paul Mietz Egli: http://developer.appcelerator.com/question/121573/how-do-i-use-so-library-in-module#answer-228134
TICONFEU,AMSTERDAM,29/06/2014
Fix build.xml
61
<project name="android" default="dist">	
	 <description>	
	 	 Ant build script for Titanium Android module android	
	 </description>	
!
	 <property name="ti.module.root" location="${basedir}"/>	
	 <property file="build.properties" />	
!
	 <import file="${titanium.platform}/../module/android/build.xml"/>	
	 	
	 <target name="post.jar">	
	 	 <copy todir="${libs}">	
	 <fileset dir="lib">	
		 <include name="**/*.so"/>	
	 </fileset>	
		 </copy>	
	 </target>	
</project>	
build.xml
Copy the .so 鍖les from lib to
libs before packaging
Paul Mietz Egli: http://developer.appcelerator.com/question/121573/how-do-i-use-so-library-in-module#answer-228134
TICONFEU,AMSTERDAM,29/06/2014
Questions?

More Related Content

Native FTW: Integrating native views in Titanium apps