java 4 iphone google
TRANSCRIPT
Developing iPhone Applicationsusing Java
Arno PuderSan Francisco State University
1. Introduction to Objective-C2. Cross-Compiling Java applications3. Demo
Outline:
Java
4iPh
one
Slide 2© A. Puder
History of Objective-C
Objective-C language was designed byBrad J. Cox:– Object-oriented extension of C. Inspired by Smalltalk.– Strict superset of C.
NeXT Software licensed the Objective-C language and develops NEXTSTEP.
FSF adds Objective-C to GNU compiler suite.
NeXT Computer and Sun Microsystems released a standardized OPENSTEP specification.
Apple acquires NeXT Software. Use for OS X. OPENSTEP now called Cocoa.
1980s
1988
1992
1994
1996
Java
4iPh
one
Slide 3© A. Puder
@interface
#import <Foundation/NSObject.h>
@interface Fraction: NSObject {int numerator;int denominator;
}-(void) print;-(void) setNumerator: (int) d;-(void) setDenominator: (int) d;-(int) numerator;-(int) denominator;@end
Java
4iPh
one
Slide 4© A. Puder
@implementation
#import "Fraction.h“#import <stdio.h>
@implementation Fraction-(void) print{ printf("%i/%i", numerator,
denominator); }-(void) setNumerator: (int) n{ numerator = n; }
-(void) setDenominator: (int) d{ denominator = d; }
-(int) denominator{ return denominator; }
-(int) numerator{ return numerator; }
@end
Java
4iPh
one
Slide 5© A. Puder
Creating and Using Objects
int main(int argc, const char *argv[]){// create a new instance FractionFraction *frac = [[Fraction alloc] init];// set the values[frac setNumerator: 1];[frac setDenominator: 3];// print itprintf("The fraction is: ");[frac print];printf("\n");// free memory[frac release];return 0;
}
Java
4iPh
one
Slide 6© A. Puder
Multiple Parameters
...-(void) setNumerator: (int) n andDenominator: (int) d;...
...-(void) setNumerator: (int) n andDenominator: (int) d{
numerator = n; denominator = d;}...
Fraction *frac = [[Fraction alloc] init];[frac setNumerator: 1 andDenominator: 5];
Invocation
setNumerator:andDenominator: is called a selector.
@interface
@implementation
Java
4iPh
one
Slide 7© A. Puder
Reference Counting
Classes inheriting from NSObject have reference counting.
Fraction *frac = [[Fraction alloc] init];printf(“Retain count: %i\n", [frac retainCount]);[frac retain]; // 2[frac retain]; // 3printf(“Retain count: %i\n", [frac retainCount]);[frac release]; // 2printf(“Retain count: %i\n", [frac retainCount]);[frac release]; // 1[frac release]; // 0. Object will be deleted
Java
4iPh
one
Slide 8© A. Puder
Autorelease Pool
Sending message autorelease will add object to autorelease pool.Releasing the pool will decrement reference counter of all managed object by 1.If reference count drops to 0, object will be deleted.Autorelease pools can be nested.Cocoa automatically adds objects to autorelease pool.
NSAutoreleasePool *pool =[[NSAutoreleasePool alloc] init];
Fraction *frac =[[[Fraction alloc] init] autorelease];
[pool release]; // ‘frac’ will be deleted
Java
4iPh
one
Slide 9© A. Puder
Dynamic Invocations
Method invocations are bound at runtime:id obj = …;[obj someMethod];
id is a generic object type (similar to java.lang.Object)obj may or may not implement someMethod. If not, a runtime error occurs.Dynamic invocations are heavily used in the delegate pattern (e.g., UITable)
Java
4iPh
one
Slide 10© A. Puder
iPhone “Hello World” in Objective-C
@interface helloWorld : UIApplication-(void) applicationDidFinishLaunching: (NSNotification) n;@end
@implementation helloWorld-(void) applicationDidFinishLaunching: (NSNotification) n{CGRect rect = [UIHardware fullScreenApplicationContentRect];UIWindow* window = [[UIWindow alloc] initWithContentRect: rect];[window orderFront: self];[window makeKey: self];[window _setHidden: false];rect.origin.x = rect.origin.y = 0;UIView* mainView = [[UIView alloc] initWithFrame: rect];[window setContentView: mainView];UITextLabel *_title = [[UITextLabel alloc] initWithFrame: rect];[_title setText: @"Hello World!"];[_title setCentersHorizontally: true];[mainView addSubview: _title];}@end
Java
4iPh
one
Slide 11© A. Puder
iPhone “Hello World” in Java
import org.xmlvm.iphone.*;
public class HelloWorld extends UIApplication{public void applicationDidFinishLaunching(NSNotification n){
CGRect rect = UIHardware.fullScreenApplicationContentRect();UIWindow window = new UIWindow(rect);window.orderFront(this);window.makeKey(this);window._setHidden(false);rect.origin.x = rect.origin.y = 0;UIView mainView = new UIView(rect);window.setContentView(mainView);UITextLabel _title = new UITextLabel(rect);_title.setText("Hello World!");_title.setCentersHorizontally(true);mainView.addSubview(_title);
}}
Java
4iPh
one
Slide 12© A. Puder
Toolchain Overview
“Hello World”Java app.
“Hello World”Objective-C
Objective-CWrapper Classes.
Native iPhone application
Cocoa JavaCompat Lib
Desktop application( iPhone emulator)
Cro
ss-C
ompi
latio
n
Java
4iPh
one
Slide 13© A. Puder
Challenges
Design goal: if possible, Java API mimics 1:1 the Objective-C API.Objective-C challenges:– Namespaces, method overloading: use name-mangling.– Garbage collection: use Objective-C reference counting.– No static member variables: use global variables.
Cocoa challenges:– Makes use of C-functions (e.g., CGColorCreate)– Uses value types (e.g., CGRect)– Uses pointers for output parameters (e.g., NSURLConnection)
– Makes heavy use of delegation (e.g., data source for UITable)
Java
4iPh
one
Slide 14© A. Puder
Example: Creating XMLVM
// Javaclass Calc {
int x;void add(int y){
x += y;}
}
Calc.java Calc.class
Calc.xml
javacBCEL/JDOM
Java
4iPh
one
Slide 15© A. Puder
Example: XMLVM of Class Calc
<?xml version="1.0" encoding="UTF-8"?><xmlvm xmlns:jvm="http://xmlvm.org/jvm"><class name="Calc">
<field name="x" type="int"/><method name="add" stack="3" locals="2">
<signature><return type="void"/><parameter type="int"/>
</signature><code><jvm:load type="Calc" index="0"/><jvm:dup/><jvm:getfield class-type="Calc" type="int" field="x"/><jvm:load type="int" index="1"/><jvm:iadd/><jvm:putfield class-type="Calc" type="int" field="x"/><jvm:return/>
</code></method>
</class></xmlvm>
Java
4iPh
one
Slide 16© A. Puder
Example: Executing XMLVM
<code><jvm:load type="Calc" index="0"/><jvm:dup/><jvm:getfield class-type="Calc" type="int" field="x"/><jvm:load type="int" index="1"/><jvm:iadd/><jvm:putfield class-type="Calc" type="int" field="x"/><jvm:return/>
</code>
locals[0]: this
locals[1]: 31
Stack:
<code>
x: 11
(y)
Java
4iPh
one
Slide 17© A. Puder
<code><jvm:load type="Calc" index="0"/><jvm:dup/><jvm:getfield class-type="Calc" type="int" field="x"/><jvm:load type="int" index="1"/><jvm:iadd/><jvm:putfield class-type="Calc" type="int" field="x"/><jvm:return/>
</code>
Example: Executing XMLVM
thisStack:
<jvm:load type="Calc" index="0"/>
locals[0]: this
locals[1]: 31
x: 11
(y)
Java
4iPh
one
Slide 18© A. Puder
<code><jvm:load type="Calc" index="0"/><jvm:dup/><jvm:getfield class-type="Calc" type="int" field="x"/><jvm:load type="int" index="1"/><jvm:iadd/><jvm:putfield class-type="Calc" type="int" field="x"/><jvm:return/>
</code>
Example: Executing XMLVM
thisthis
Stack:
<jvm:dup/>
locals[0]: this
locals[1]: 31
x: 11
(y)
Java
4iPh
one
Slide 19© A. Puder
<code><jvm:load type="Calc" index="0"/><jvm:dup/><jvm:getfield class-type="Calc" type="int" field="x"/><jvm:load type="int" index="1"/><jvm:iadd/><jvm:putfield class-type="Calc" type="int" field="x"/><jvm:return/>
</code>
Example: Executing XMLVM
this11
Stack:
<jvm:getfield class-type="Calc" type="int" field="x"/>
locals[0]: this
locals[1]: 31
x: 11
(y)
Java
4iPh
one
Slide 20© A. Puder
<code><jvm:load type="Calc" index="0"/><jvm:dup/><jvm:getfield class-type="Calc" type="int" field="x"/><jvm:load type="int" index="1"/><jvm:iadd/><jvm:putfield class-type="Calc" type="int" field="x"/><jvm:return/>
</code>
Example: Executing XMLVM
this1131
Stack:
<jvm:load type="int" index="1"/>
locals[0]: this
locals[1]: 31
x: 11
(y)
Java
4iPh
one
Slide 21© A. Puder
<code><jvm:load type="Calc" index="0"/><jvm:dup/><jvm:getfield class-type="Calc" type="int" field="x"/><jvm:load type="int" index="1"/><jvm:iadd/><jvm:putfield class-type="Calc" type="int" field="x"/><jvm:return/>
</code>
Example: Executing XMLVM
this42
Stack:
<jvm:iadd/>
locals[0]: this
locals[1]: 31
x: 11
(y)
Java
4iPh
one
Slide 22© A. Puder
<code><jvm:load type="Calc" index="0"/><jvm:dup/><jvm:getfield class-type="Calc" type="int" field="x"/><jvm:load type="int" index="1"/><jvm:iadd/><jvm:putfield class-type="Calc" type="int" field="x"/><jvm:return/>
</code>
Example: Executing XMLVM
Stack:
<jvm:putfield class-type="Calc" type="int" field="x"/>
locals[0]: this
locals[1]: 31
x: 42
(y)
Java
4iPh
one
Slide 23© A. Puder
Cross-Compiling XMLVM to Objective-CSince the Java VM is a simple, stack-based machine, XMLVM can easily be mapped to other languages.Simply mimic stack machine using target language!These translations are done using XSLT.Mappings exist for different languages.The XSLT excerpt below demonstrates the translation of <jvm:iadd/> (Integer add) to Objective-C.
// Objective-Ctypedef union {
id o;int i;float f;double d;
} XMLVMElem;
<!– XSL template --><xsl:template match="jvm:iadd">
<xsl:text>_op2.i = _stack[--_sp].i; // Pop operand 1_op1.i = _stack[--_sp].i; // Pop operand 2_stack[_sp++].i = _op1.i + _op2.i; // Push sum
</xsl:text></xsl:template>
_op1, _op2, and_stack are based on
XMLVMElem
Java
4iPh
one
Slide 24© A. Puder
Example: Class Calc in Objective-C
// Objective-C generated via stylesheet @implementation Calc;
-(void) add___int :(int)n1 {
XMLVMElem _stack[3];XMLVMElem _locals[2];int _sp = 0;XMLVMElem _op1, _op2; NSAutoreleasePool* _pool = [[NSAutoreleasePool alloc] init]; _locals[0].o = self; _locals[1].i = n1; _stack[_sp++].o = _locals[0].o; _op1 = _stack[_sp - 1]; _stack[_sp++] = _op1; _op1.o = _stack[--_sp].o; _op2.i = ((Calc*) _op1.o)->x; _stack[_sp++].i = _op2.i; _op1.i = _locals[1].i; _stack[_sp++].i = _op1.i; _op2.i = _stack[--_sp].i; _op1.i = _stack[--_sp].i; _stack[_sp++].i = _op1.i + _op2.i;_op1.i = _stack[--_sp].i; _op2.o = _stack[--_sp].o; ((Calc*) _op2.o)->x = _op1.i; [_pool release]; return;
} @end
<load>
<dup>
<getfield>
<load>
<iadd>
<putfield>
<return>
Java
4iPh
one
Slide 25© A. Puder
XMLVM Tool Chain
Java
4iPh
one
Slide 26© A. Puder
Abstract Virtual Machine
Currently several flavors of XMLVM:– XMLVMJVM: Java byte code– XMLVMCLR: .NET byte code– XMLVMYARV: Ruby YARV byte code
Idea: XMLVMAVM: heterogeneous mix of instructions from different virtual machines.Application: Aspect Oriented Programming (AOP).Challenge: define operational semantics of XMLVMAVM.
C# Application
XMLVMAVM
Java Aspect
Byte Code Weaver
Java
4iPh
one
Slide 27© A. Puder
Outlook
Still lots to do:– Complete Java-to-Objective-C mapping.– Support for all iPhone UI elements.
.NET Cocoa compatibility classes.Android -> iPhone cross-compilation.
http://xmlvm.org
Java
4iPh
one
Slide 28© A. Puder
Installing the Toolchain
Prerequisites for running the iPhone simulator:– Java 5 or 6– Eclipse
Prerequisites for cross-compiling to the iPhone:– Jail-broken iPhone/iPod Touch:
http://www.ziphone.org/– iPhone development toolchain:
http://code.google.com/p/iphone-dev/wiki/BuildingXMLVM Cross-Compiler and iPhone simulator available from SourceForge:http://sourceforge.net/cvs/?group_id=152977Use anonymous CVS to checkout module ‘xmlvm’.
Java
4iPh
one
Slide 29© A. Puder
Running the Simulator
Simulator automatically launched when a Java-based iPhone application is executed.Currently there are four demos:– org.xmlvm.test.iphone.HelloWorld– org.xmlvm.test.iphone.Android– org.xmlvm.test.iphone.ifireworks.Main
– org.xmlvm.test.iphone.todo.Main
All these applications are in source folder src/test/iphone
The implementation of the iPhone simulator is in source folder src/xmlvm2objc/compat-lib/javaThe remote control application is in org.xmlvm.iphone.remote.Main
Java
4iPh
one
Slide 30© A. Puder
Cross-Compiling “Hello World” to Objective-C
The cross-compiler is in source folder src/xmlvm class org.xmlvm.MainTo generate the XMLVM for “Hello World” use the following command line options (under Eclipse):--console ${workspace_loc:xmlvm}/bin/org/xmlvm/test/iphone/HelloWorld.classTo cross-compile the XMLVM to Objective-C use:--console --objc${workspace_loc:xmlvm}/bin/org/xmlvm/test/iphone/HelloWorld.classTo write the Objective-C source code to a file, use:--out=tmp --objc${workspace_loc:xmlvm}/bin/org/xmlvm/test/iphone/HelloWorld.classThe previous command will generate two files:– ${workspace_loc:xmlvm}/tmp/HelloWorld.h– ${workspace_loc:xmlvm}/tmp/HelloWorld.m
Java
4iPh
one
Slide 31© A. Puder
Info.plist
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN“"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"><dict>
<key>CFBundleDevelopmentRegion</key><string>English</string><key>CFBundleExecutable</key><string>HelloWorld</string><key>CFBundleIdentifier</key><string>org.puder.HelloWorld</string><key>CFBundleInfoDictionaryVersion</key><string>6.0</string><key>CFBundlePackageType</key><string>APPL</string><key>CFBundleSignature</key><string>????</string><key>CFBundleVersion</key><string>1.0</string>
</dict></plist>
Java
4iPh
one
Slide 32© A. Puder
Makefile 1/3
PRODUCT_NAME=HelloWorldSOURCES=\
HelloWorld.m \../bin/XMLVMCompatLib.m
SRCROOT=.BUILT_PRODUCTS_DIR=buildCONFIGURATION_TEMP_DIR=objINFOPLIST_FILE=Info.plist
CC=arm-apple-darwin-gccCFLAGS=-g -O2 -Wall -I. -I../binLD=$(CC)LDFLAGS=-lobjc -ObjC -framework CoreFoundation \
-framework Foundation -framework CoreGraphics \-framework GraphicsServices \-framework UIKit -framework LayerKit
Java
4iPh
one
Slide 33© A. Puder
Makefile 2/3
WRAPPER_NAME=$(PRODUCT_NAME).appEXECUTABLE_NAME=$(PRODUCT_NAME)SOURCES_ABS=$(addprefix $(SRCROOT)/,$(SOURCES))INFOPLIST_ABS=$(addprefix $(SRCROOT)/,$(INFOPLIST_FILE))OBJECTS=\
$(patsubst %.c,%.o,$(filter %.c,$(SOURCES))) \$(patsubst %.cc,%.o,$(filter %.cc,$(SOURCES))) \$(patsubst %.cpp,%.o,$(filter %.cpp,$(SOURCES))) \$(patsubst %.m,%.o,$(filter %.m,$(SOURCES))) \$(patsubst %.mm,%.o,$(filter %.mm,$(SOURCES)))
OBJECTS_ABS=$(addprefix $(CONFIGURATION_TEMP_DIR)/,$(OBJECTS))APP_ABS=$(BUILT_PRODUCTS_DIR)/$(WRAPPER_NAME)PRODUCT_ABS=$(APP_ABS)/$(EXECUTABLE_NAME)
all: $(PRODUCT_ABS)
Java
4iPh
one
Slide 34© A. Puder
Makefile 3/3
$(PRODUCT_ABS): $(APP_ABS) $(OBJECTS_ABS)$(LD) $(LDFLAGS) -o $(PRODUCT_ABS) $(OBJECTS_ABS)
$(APP_ABS): $(INFOPLIST_ABS)mkdir -p $(APP_ABS)cp $(INFOPLIST_ABS) $(APP_ABS)/cp $(SRCROOT)/$(RESOURCES)/*.png $(APP_ABS)/
$(CONFIGURATION_TEMP_DIR)/%.o: $(SRCROOT)/%.mmkdir -p $(dir $@)$(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@
deploy:cd build; scp -r $(WRAPPER_NAME) \
[email protected]:/Applications
clean:rm -rf $(CONFIGURATION_TEMP_DIR)rm -rf $(BUILT_PRODUCTS_DIR)rm -f *~
Java
4iPh
one
Slide 35© A. Puder
Compile and run “Hello World”
Type “make” in ${workspace_loc:xmlvm}/tmpType “make deploy”On the iPhone, type “killall SpringBoard”The previous command can be accomplished by either ssh-ing into the iPhone, or by using a terminal application on the iPhone.Restarting the SpringBoard is necessary only once so that it picks up the new “Hello World” application.