Visage Android Hands-on Lab

steveonjava 1,959 views 80 slides May 16, 2011
Slide 1
Slide 1 of 80
Slide 1
1
Slide 2
2
Slide 3
3
Slide 4
4
Slide 5
5
Slide 6
6
Slide 7
7
Slide 8
8
Slide 9
9
Slide 10
10
Slide 11
11
Slide 12
12
Slide 13
13
Slide 14
14
Slide 15
15
Slide 16
16
Slide 17
17
Slide 18
18
Slide 19
19
Slide 20
20
Slide 21
21
Slide 22
22
Slide 23
23
Slide 24
24
Slide 25
25
Slide 26
26
Slide 27
27
Slide 28
28
Slide 29
29
Slide 30
30
Slide 31
31
Slide 32
32
Slide 33
33
Slide 34
34
Slide 35
35
Slide 36
36
Slide 37
37
Slide 38
38
Slide 39
39
Slide 40
40
Slide 41
41
Slide 42
42
Slide 43
43
Slide 44
44
Slide 45
45
Slide 46
46
Slide 47
47
Slide 48
48
Slide 49
49
Slide 50
50
Slide 51
51
Slide 52
52
Slide 53
53
Slide 54
54
Slide 55
55
Slide 56
56
Slide 57
57
Slide 58
58
Slide 59
59
Slide 60
60
Slide 61
61
Slide 62
62
Slide 63
63
Slide 64
64
Slide 65
65
Slide 66
66
Slide 67
67
Slide 68
68
Slide 69
69
Slide 70
70
Slide 71
71
Slide 72
72
Slide 73
73
Slide 74
74
Slide 75
75
Slide 76
76
Slide 77
77
Slide 78
78
Slide 79
79
Slide 80
80

About This Presentation

Hands-on lab given at #geecon for Visage Android development. A full VirtualBox image for running through the lab yourself is supplied here:
http://projavafx.com/VisageLab/


Slide Content

Visage Android Hands-on Lab Stephen Chin – GXS http://steveonjava.com/

The Visage Language 2 Statically Compiled Language Based on F3 / JavaFX Script Planning Support for Different Platforms: JavaFX 2.0 Android Apache Pivot Flex JSF “Visage is a domain specific language (DSL) designed for the express purpose of writing user interfaces.”

Language Features Declarative Object Construction Code looks like the UI it is representing. Data Binding Variables can be bound to UI state, allowing automatic updates and behavior to be triggered. Behavior Encapsulation Visage provides closures to make it easy to implement event handlers or other behavior-driven logic. Null Safety Application logic will proceed even if intermediate variables are undefined or null. 3

Hello World Visage Stage {   title : "Hello World"   Scene {     Text {       "Hello World"     }   } } 4

Visage on Android 5 Visage Runs as a Native App on Android Full Access to all the Android APIs Declarative Layer on Top of Android APIs

6 Java vs. visage Lesson 1

Language Similarities Java is… Statically typed Compiled to bytecodes Runs on the JVM Has a large library Visage is… Statically typed Compiled to bytecodes Runs on the JVM Can call Java libraries 7

Language Differences 8

Integrating Visage and Java Calling Java from Visage Can call Java interface or classes directly Automatic conversion to and from Arrays and Collections Can even extend Java interfaces and classes Calling Visage from Java Easiest way is to create a Java interface that Visage extends Can invoke Visage as a script and get results back 9

Hello World , Visage Module 1 10

Exercise 1.A – Android Setup Setup and run the VirtualBox image Create an emulator instance Create a new Android project from the command line Run the project in the emulator 11

Setting Up Your Machine Copy these files off the USB stick: VirtualBox for your platform (mac or windows) VisageLab folder Decompress VisageLab / Visage Dev2.vdi.zip Install VirtualBox Open Visage Dev.vbox 12

Setting Up Your Machine Download and Install the Android SDK http://developer.android.com/sdk/index.html Download the Visage SDK http://code.google.com/p/visage/downloads/list Install the Android/Visage SDK On the USB stick 13

Set Up Your Device for Debugging And mount it from: Devices > USB Devices > (your-device-name) 14 14

Or Create a Virtual Android Device 15 Launch the AVD Manager by typing: android

Setting Up Your Project Project creation command: android create project –t 1 –p HelloVisage –k org.test –a HelloVisage Arguments: n : Project name (optional) t : Target ID of the new project (required) p : Project directory (required) k : Package name for the application (required) a : Name of the default Activity (required) 16

Android XML Code <? xml version="1.0" encoding ="utf-8"? > < LinearLayout xmlns:android ="http:// schemas.android.com / apk / res / android " android:orientation =" vertical" android:layout_width =" fill_parent " android:layout_height =" fill_parent " > < TextView android:layout_width =" fill_parent " android:layout_height =" wrap_content " android:text ="Hello World, HelloVisage " / > < / LinearLayout > 17

Plus some more Java… public class HelloVisage extends Activity { /** Called when the activity is first created. * / @ Override public void onCreate (Bundle savedIS ) { super.onCreate ( savedIS ); setContentView ( R.layout.main ) ; } } 18

Run Your Project cd HelloVisage ant install Open it in the applications menu 19

Exercise 1.B – All Java Conversion Make sure you have the basic project running first Convert the XML Code to Java Run the all Java project You should get identical results 20

Converted XML Code (simplified) public class HelloVisage extends Activity { @Override public void onCreate (Bundle savedIS ) { super.onCreate ( savedIS ) ; Context context = getApplicationContext (); LinearLayout layout = new LinearLayout (context); layout.setOrientation ( LinearLayout.VERTICAL ); TextView text = new TextView (context); text.setText ("Hello World, Java Only" ); layout.addView (text); setContentView (layout); } } 21

(and here are the imports…) import android.app.Activity ; import android.content.Context ; import android.os.Bundle ; import android.widget.LinearLayout ; import android.widget.TextView ; 22

Exercise 1.C – DDMS Debugging So you made a mistake in your code… the compiler can’t catch everything (even if you didn’t make a mistake, force one… a beautiful NullPointerException will do) Launch DDMS and select your emulator/device 23

Break the code (change in bold) public class HelloVisage extends Activity { @Override public void onCreate (Bundle savedIS ) { super.onCreate ( savedIS ) ; Context context = getApplicationContext (); LinearLayout layout = null;//new LinearLayout (context); layout.setOrientation ( LinearLayout.VERTICAL ); TextView text = new TextView (context); text.setText ("Hello World, HelloVisage "); layout.addView (text); setContentView (layout); } } 24

DDMS Displaying a Stack Trace 25

Exercise 1.D – Visage Port Modify the build script to compile Visage Copy the Visage Runtime libraries Convert the Java code to Visage Run on device/emulator 26

Modify the Build Script (1) <target name="-post-compile"> <path id=" android.classpath "> < fileset dir ="./libs" includes="*.jar" /> <path refid =" android.target.classpath "/> < pathelement location="${ out.classes.absolute.dir }"/> </path> < pathconvert refid =" android.classpath " property=" androidcpath "/> <path id =" visage.sources "> < fileset dir ="${ source.absolute.dir }" includes="**/*. fx "/> </path > 27

Modify the Build Script (2) < pathconvert refid =" visage.sources " property=" visagepath " pathsep =" "/> <exec executable="${ visagehome }/bin/ javafxc ${ binary.extension }" failonerror ="true" logerror ="true"> < arg value="-d"/> < arg value="${ out.classes.absolute.dir }"/> < arg value="- cp "/> < arg value="${ androidcpath }"/> < arg line="${ visagepath }"/> </exec> </target> 28

Add Some Properties… local.properties : visagehome =/home/visage/visage- sdk binary.extension = 29

Copy Over the Runtime JAR Copy: javafxrt.jar From: $ visagehome /lib/shared/ To: $ projectdir /libs 30

Straight JavaFX Conversion... public class Test extends Activity { override function onCreate ( savedInstanceState:Bundle ) { super.onCreate ( savedInstanceState ); def context = getApplicationContext (); def layout = new LinearLayout (context) ; layout.setOrientation ( LinearLayout.VERTICAL ); def text = new TextView (context); text.setText ("Hello World, Hello Long Visage " ) ; layout.addView (text); setContentView (layout); } } 31

Rename your source file *.java -> *. fx 32

Exercise 1.E – Simplified Visage Include the visage-android jar Modify the Visage code to use the new APIs Run on device/emulator 33

Copy the visage-android JAR Copy: visage- android.jar From: /home/visage/visage-android/ dist / To: $ projectdir / libs 34

Android JavaFX Code public class HelloVisage extends Activity { override var view = LinearLayout { orientation: Orientation.VERTICAL view: TextView { text: "Hello World, Beautified Visage " } } } 35

And change the imports… org.visage.android.app.Activity ; org.visage.android.widget.LinearLayout ; org.visage.android.widget.Orientation ; org.visage.android.widget.TextView ; 36

Working Hello Visage Application 37

Visage Language Fundamentals Lesson 2 38

Datatype Support DataType Java Equivalent Range Examples Boolean boolean true or false true, false Integer int -2147483648 to 2147483647 2009, 03731, 0x07d9 Number Float 1.40×10 -45 and 3.40×10 38 3.14, 3e8, 1.380E-23 String String N/A "java's", 'in"side"er' Duration <None> -2 63 to 2 63 -1 milliseconds 1h, 5m, 30s, 500ms Length <None> dp , sp , em , %, mm, cm, in 2mm, 5sp, 1in Angle <None> rad, deg , turn 1rad, 30deg Color <None> #RRGGBB, #RGB, #RRGGBB|AA, #RGB|A #CCCCCC, #202020|D0 Character char 0 to 65535 0, 20, 32 Byte byte -128 to 127 -5, 0, 5 Short short -32768 to 32767 -300, 0, 521 Long long -2 63 to 2 63 -1 2009, 03731, 0x07d9 Float float 1.40×10 -45 and 3.40×10 38 3.14, 3e8, 1.380E-23 Double double 4.94×10 -324 and 1.80×10 308 3.14, 3e231, 1.380E-123 39

Visage Operators Operator Meaning Precedence Examples ++ Pre/post increment 1 ++i, i++ -- Pre/post decrement 1 --i, i-- not Boolean negation 2 not ( cond ) * Multiply 3 2 * 5, 1h * 4 / Divide 3 9 / 3, 1m / 3 mod Modulo 3 20 mod 3 + Add 4 0 + 2, 1m + 20s - Subtract (or negate) 4 (2) -2, 32 -3, 1h -5m 40 Multiplication and division of two durations is allowed, but not meaningful Underflows/Overflows will fail silently, producing inaccurate results Divide by zero will throw a runtime exception

Visage Operators (continued) Operator Meaning Precedence Examples == Equal 5 value1 == value2, 4 == 4 != Not equal 5 value1 != value2, 5 != 4 < Lessthan 5 value1 < value2, 4 < 5 <= Lessthanorequal 5 value1 <= value2, 5 <= 5 > Greater than 5 value1 > value2, 6 > 5 >= Greater than or equal 5 value1 >= value2, 6 >= 6 instanceof Is instance of class 6 node instanceof Text as Typecast to class 6 node as Text and Boolean and 7 cond1 and cond2 or Boolean or 8 cond1 or cond2 += Add and assign 9 value += 5 -= Subtract and assign 9 value -= 3 *= Multiply and assign 9 value *= 2 /= Divide and assign 9 value /=4 = Assign 9 value = 7 41

Access Modifiers Modifier Name Description <default> Script only access Only accessible within the same script file package Package access Only accessible within the same package protected Protected access Only accessible within the same package or by subclasses. public Public access Can be accessed anywhere. public-read Read access modifier Var /def modifier to allow a variable to be read anywhere public-init Init access modifier Var /def modifier to allow a variable to be initialized or read anywhere 42

Data Binding A variable or a constant can be bound to an expression var x = bind a + b; The bound expression is remembered The dependencies of the expression is watched Variable is updated lazily when possible 43

CONTROLS AND SETTINGS Module 2 44

Exercise 2.A – NetBeans Integration Create a new JavaFX NetBeans project Merge in build scripts from Android project Start coding! 45

Create a new JavaFX Project File > New Project… Name the project “ ConfigReporter ” In package " org.test " 46

Merging Project Folders Copy these files over: *.properties AndroidManifest.xml res/ libs/ proguard.cfg build.xml [replace] 47

Merging Build Scripts Update the build.xml file: Set the project name to “ ConfigReporter ” Update the strings.xml file: Set the app_name to “ ConfigReporter ” Load the NetBeans property files (in build.xml ):  < property file=" nbproject /private/ config.properties "/ > < property file=" nbproject /private/ configs /${ config }.properties"/ > < property file=" nbproject /private/ private.properties "/ > < property file="${ user.properties.file }"/ > < property file=" nbproject / configs /${ config }.properties"/ > < property file=" nbproject / project.properties "/> 48

Alias NetBeans Targets:  < target name="launch" depends=" install”> < exec executable="${ adb }" failonerror =" true"> < arg line="${ adb.device.arg }"/ > < arg value="shell"/ > < arg value="am"/ > < arg value="start"/ > < arg value="-n"/ > < arg value =” org.test /. ConfigReporter " / > < arg value="-a"/ > < arg value=" android.intent.action.MAIN "/ > < /exec > < /target > < target name="jar" depends="compile"/ > < target name="run" depends="launch"/> 49

Update AndroidManifest.xml Change project name to " ConfigReporter " 50

Modify Project Properties Set JavaFX Platform to “ Visage_SDK ” Add Libraries: “libs” folder a ndroid.jar 51

Update ConfigReporter.fx Make it extend the visage Activity class For now, you can copy the logic from HelloVisage 52

Exercise 2.C – Android Controls Create a Text Field Create an Edit Box Wire them up using Binding 53

Bound Controls (1) override var view = LinearLayout { orientation: Orientation.VERTICAL var secret:String ; view: [ EditText { hint: "Super Secret Text” password: true text: bind secret with inverse 54

Bound Controls (2) } TextView { text: "Is Revealed!! !” } TextView { text: bind secret } ] } 55

Exercise 2.D – Button Handler Create a Button Control Add an onClick handler Make something happen (maybe a bind) 56

Button onClick handler Button { text: "Launch Settings" onClick : function() { startActivity (new Intent(this, Settings.class )); setting = "Launching..."; } } TextView { text: "Setting is:" } TextView { text: bind setting } 57

Exercise 2.E – Android Settings Create a Settings Activity Populate it with the following preferences: Text Password List Launch it from the Button control 58

Settings Class public class Settings extends PreferenceActivity { var usernamePref:EditTextPreference ; var passwordPref:EditTextPreference ; var pollingPref:ListPreference ; override var screen = PreferenceScreen { preferences: [ … 59

Text Preference PreferenceCategory { title: " Preferences" preferences: [ usernamePref = EditTextPreference { title: " Username" key: " usernamePref " summary: bind if ( usernamePref.text == "") "Currently undefined" else "Current value: { usernamePref.text }" } 60

Password Preference passwordPref = EditTextPreference { title : " Password” key : " passwordPref ” summary : bind passwordPref.text.replaceAll (".", "*"); } 61

List Preference pollingPref = ListPreference { title : "Polling Interval" key : " pollingPref " defaultValue : "60000" entries : ["30 seconds", "1 minute", "5 minutes", "10 minutes", "15 minutes", "30 minutes", "1 hour"] entryValues : ["30000", "60000", "300000", "600000", "900000", "1800000", "3600000"] summary : bind pollingPref.entry } 62

Service Metadata Update AndroidManifest.xml : < activity android:name =".Settings" android:label ="@string/ settings_label "/ > Update string.xml : <string name=" settings_label ">Settings</ string > 63

Invoke the new service In the onClick handler:  startActivity (new Intent(this, Settings.class )); 64

Working Settings Panel 65

Advanced Javafx sequences Lesson 3 66

What Bind Updates var x = bind if(a) then b else c x is updated if a or b or c changes var x = bind for ( i in [a..b]) { i * i } Not everything is recalculated If a = 1 and b = 2 , x is [1, 4] If b changes to 3 , only the added element is calculated 67 1 4 9

Binding to Expressions Binding to a block Bound block may contain any number of defs followed by one expression Dependencies of block is backtraced from the expression Binding to function invocation expression Regular function: dependencies are parameters Bound function: backtraced from final expression inside function 68

Binding to Object Literals var a = 3; var b = 4; var p = bind Point { x: a, y: b }; var q = bind Point { x: bind a, y: b }; var r = bind Point { x: bind a, y: bind b }; When a changes: p gets a new instance of Point q and r keep the old instance with a new x value r will never get a new instance of Point (the outer bind in r is useless) 69

Visage Sequences Represents collections of homogeneous data A fundamental container data type Rich set of language facilities Contributor to declarative syntax Automatic conversion to and from Java Arrays and Collections 70

Creating Sequences Explicit sequence expression [1, 3, 5, 7, 9] Elements are separated by commas Comma may be omitted if element ends with brace 71 1 3 5 7 9

Creating Sequences Numeric sequence with range expressions: [1..10] Can have a step: [1..10 step 2] [0.0..0.9 step 0.1] Can be decreasing: [10..1 step -3] Beware of step that goes opposite direction: [10..1] is [] Exclusive right end [1..<5] 72 1 2 3 4 5 6 7 8 9 10 1 3 5 7 9 .1 .2 .3 .4 .5 .6 .7 .8 .9 10 7 4 1 1 2 3 4

Getting Info from Sequences ints = [1, 3, 5, 7, 9] sizeof ints is 5 ints [0] is 1 , ints [1] is 3 , ..., ints [4] is 9 ints [-1] is (default value of Integer), so is ints [5] For a sequence of objects, the default is null 73 1 3 5 7 9 [0] [1] [2] [3] [4]

Getting Slices from Sequences ints = [1, 3, 5, 7, 9] ints [0..2] is [1, 3, 5] ints [0..<2] is [1, 3] ints [2..] is [5, 7, 9] ints [2..<] is [5, 7] ints [2..0], ints [-2..-1], ints [5..6] are all []s 74 1 3 5 7 9 [0] [1] [2] [3] [4]

Getting Subsets from Sequences ints = [1, 3, 5, 7, 9] ints [k | k > 6] is: [7, 9] (k > 6 is a condition) ints [k | indexof k < 2] is: [1, 3] ints [k | k > 10] is: [] 75 1 3 5 7 9 [0] [1] [2] [3] [4]

Inserting into Sequences ints = [1, 3, 5, 7, 9] insert 20 into ints insert 30 before ints [2] insert 40 after ints [4] insert [50, 60] into ints 76 1 3 5 7 9 1 3 5 7 9 1 3 5 7 9 20 20 30 1 3 5 7 9 20 30 40 1 3 5 7 9 20 30 40 50 60

Deleting from Sequences ints = [1, 3, 5, 7, 9] delete 7 from ints delete ints [0] delete ints [0..1] delete ints : ints becomes [] 1 3 5 7 9 1 3 5 9 3 5 9 9 1 3 5 7 9

Sequence Puzzlers What is the size of this sequence: [1..10 step -1] What does this evaluate to: [10..<20 step 2][ k|k >17] What is the size of this sequence: sizeof [20..1 step -3] 78 1 2 3 A: 0 A: 1 A: [18]

EXTENDING VISAGE ANDROID APIs Module 3 79 Become a Visage contributor! Join me in the Hackergarten after the session

80 Stephen Chin http://steveonjava.com/ Tweet: @ steveonjava Thank You