Visage Android Hands-on Lab (OSCON)

80
Visage Android Hands-on Lab Stephen Chin Chief Agile Methodologist – GXS OSCON Java Program Chair http://steveonjava.com/ Tweet: @steveonjava

description

Lab session given at OSCON Java 2011:Visage is the successor to the JavaFX Script Language, a domain-specific language for writing UIs. It excels at rapid application design and can be used on any platform that supports Java. In this lab you will have an opportunity to write Visage applications that deploy to and run on Android mobile devices. No prior experience with Android or Visage development is required.

Transcript of Visage Android Hands-on Lab (OSCON)

Page 1: Visage Android Hands-on Lab (OSCON)

Visage Android Hands-on Lab Stephen Chin Chief Agile Methodologist – GXS OSCON Java Program Chair http://steveonjava.com/ Tweet: @steveonjava

Page 2: Visage Android Hands-on Lab (OSCON)

How This Session Works

Team A

Team B

Team C

Page 3: Visage Android Hands-on Lab (OSCON)

The Visage Language

3

§ 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.”

Page 4: Visage Android Hands-on Lab (OSCON)

What Does Visage Look Like? Stage { var input:TextBox; title: bind input.text Scene { input = TextBox { color: #DDCC33 } } }  

4

Page 5: Visage Android Hands-on Lab (OSCON)

UI Focused 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. § UI Definition Literals - Built-in literal syntax for colors, angles, lengths, and durations § Null Safety - Application logic will proceed even if intermediate variables are undefined

or null.

5

Page 6: Visage Android Hands-on Lab (OSCON)

Visage on Android

6

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

Page 7: Visage Android Hands-on Lab (OSCON)

HELLO WORLD, VISAGE Module 1

7

Page 8: Visage Android Hands-on Lab (OSCON)

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

8

Page 9: Visage Android Hands-on Lab (OSCON)

Setting Up Your Machine 1.  Copy these files off the USB stick

(or from http://projavafx.com/VisageLab/): - VirtualBox for your platform (Mac, Windows, or Linux) - VisageLab folder

1.  Decompress VisageLab/Visage Dev2.vdi.zip

2.  Install VirtualBox 3.  Open Visage Dev.vbox

9

Page 10: Visage Android Hands-on Lab (OSCON)

Set Up Your Device for Debugging

§ And mount it from: - Devices > USB Devices > (your-device-name)

10 10

Page 11: Visage Android Hands-on Lab (OSCON)

Or Create a Virtual Android Device

11

§ Launch the AVD Manager by typing: android

Page 12: Visage Android Hands-on Lab (OSCON)

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)

12

Page 13: Visage Android Hands-on Lab (OSCON)

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>

13

Page 14: Visage Android Hands-on Lab (OSCON)

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); } }

14

Page 15: Visage Android Hands-on Lab (OSCON)

Run Your Project § cd HelloVisage § ant install

§ Open it in the applications menu

15

Page 16: Visage Android Hands-on Lab (OSCON)

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

16

Page 17: Visage Android Hands-on Lab (OSCON)

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); } }

17

Page 18: Visage Android Hands-on Lab (OSCON)

(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;

18

Page 19: Visage Android Hands-on Lab (OSCON)

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

19

Page 20: Visage Android Hands-on Lab (OSCON)

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); } }

20

Page 21: Visage Android Hands-on Lab (OSCON)

DDMS Displaying a Stack Trace

21

Page 22: Visage Android Hands-on Lab (OSCON)

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

22

Page 23: Visage Android Hands-on Lab (OSCON)

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>

23

Page 24: Visage Android Hands-on Lab (OSCON)

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>

24

Page 25: Visage Android Hands-on Lab (OSCON)

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

25

Page 26: Visage Android Hands-on Lab (OSCON)

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

26

Page 27: Visage Android Hands-on Lab (OSCON)

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); } }

27

Page 28: Visage Android Hands-on Lab (OSCON)

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

28

Page 29: Visage Android Hands-on Lab (OSCON)

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

29

Page 30: Visage Android Hands-on Lab (OSCON)

Copy the visage-android JAR § Copy:

visage-android.jar § From:

/home/visage/visage-android/dist/ § To:

$projectdir/libs

30

Page 31: Visage Android Hands-on Lab (OSCON)

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

31

Page 32: Visage Android Hands-on Lab (OSCON)

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

32

Page 33: Visage Android Hands-on Lab (OSCON)

Working Hello Visage Application

33

Page 34: Visage Android Hands-on Lab (OSCON)

34

JAVA VS. VISAGE Lesson 1

Page 35: Visage Android Hands-on Lab (OSCON)

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

35

Page 36: Visage Android Hands-on Lab (OSCON)

Language Differences

36

Visage • Type Inferencing • Closures • Binding • Sequences • Animation Syntax

Java • Annotations • Generics • Multi-Threading

Page 37: Visage Android Hands-on Lab (OSCON)

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

37

Page 38: Visage Android Hands-on Lab (OSCON)

VISAGE LANGUAGE FUNDAMENTALS Lesson 2

38

Page 39: Visage Android Hands-on Lab (OSCON)

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×1038   3.14, 3e8, 1.380E-23  

String   String   N/A   "java's", 'in"side"er'  

Duration   <None>   -263 to 263-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   -263 to 263-1   2009, 03731, 0x07d9  

Float   float   1.40×10-45 and 3.40×1038   3.14, 3e8, 1.380E-23  

Double   double   4.94×10-324 and 1.80×10308   3.14, 3e231, 1.380E-123  

39

Page 40: Visage Android Hands-on Lab (OSCON)

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

Page 41: Visage Android Hands-on Lab (OSCON)

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

Page 42: Visage Android Hands-on Lab (OSCON)

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

Page 43: Visage Android Hands-on Lab (OSCON)

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

Page 44: Visage Android Hands-on Lab (OSCON)

CONTROLS AND SETTINGS Module 2

44

Page 45: Visage Android Hands-on Lab (OSCON)

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

45

Page 46: Visage Android Hands-on Lab (OSCON)

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

46

Page 47: Visage Android Hands-on Lab (OSCON)

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

47

Page 48: Visage Android Hands-on Lab (OSCON)

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

Page 49: Visage Android Hands-on Lab (OSCON)

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

Page 50: Visage Android Hands-on Lab (OSCON)

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

50

Page 51: Visage Android Hands-on Lab (OSCON)

Modify Project Properties § Set JavaFX Platform to “Visage_SDK” § Add Libraries: -  “libs” folder -  android.jar

51

Page 52: Visage Android Hands-on Lab (OSCON)

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

52

Page 53: Visage Android Hands-on Lab (OSCON)

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

53

Page 54: Visage Android Hands-on Lab (OSCON)

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

Page 55: Visage Android Hands-on Lab (OSCON)

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

55

Page 56: Visage Android Hands-on Lab (OSCON)

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

56

Page 57: Visage Android Hands-on Lab (OSCON)

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

Page 58: Visage Android Hands-on Lab (OSCON)

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

Page 59: Visage Android Hands-on Lab (OSCON)

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

59

Page 60: Visage Android Hands-on Lab (OSCON)

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

Page 61: Visage Android Hands-on Lab (OSCON)

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

61

Page 62: Visage Android Hands-on Lab (OSCON)

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

Page 63: Visage Android Hands-on Lab (OSCON)

Service Metadata § Update AndroidManifest.xml:

<activity android:name=".Settings” android:label="@string/settings_label"/>

§ Update string.xml: <string name="settings_label">Settings</string>

63

Page 64: Visage Android Hands-on Lab (OSCON)

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

64

Page 65: Visage Android Hands-on Lab (OSCON)

Working Settings Panel

65

Page 66: Visage Android Hands-on Lab (OSCON)

ADVANCED JAVAFX SEQUENCES Lesson 3

66

Page 67: Visage Android Hands-on Lab (OSCON)

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

Page 68: Visage Android Hands-on Lab (OSCON)

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

Page 69: Visage Android Hands-on Lab (OSCON)

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

Page 70: Visage Android Hands-on Lab (OSCON)

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

Page 71: Visage Android Hands-on Lab (OSCON)

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

Page 72: Visage Android Hands-on Lab (OSCON)

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]

1 2 3 4 5 6 7 8 9 10

1 3 5 7 9 0 .1 .2 .3 .4 .5 .6 .7 .8 .9

10 7 4 1

1 2 3 4

Page 73: Visage Android Hands-on Lab (OSCON)

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 0 (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]

Page 74: Visage Android Hands-on Lab (OSCON)

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]

Page 75: Visage Android Hands-on Lab (OSCON)

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]

Page 76: Visage Android Hands-on Lab (OSCON)

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

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

Page 77: Visage Android Hands-on Lab (OSCON)

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

Page 78: Visage Android Hands-on Lab (OSCON)

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]

Page 79: Visage Android Hands-on Lab (OSCON)

How Did I Do?

Page 80: Visage Android Hands-on Lab (OSCON)

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

80