$30 off During Our Annual Pro Sale. View Details »

Ruboto - JRuby on Android at JRubyConf.eu 2012

Ruboto - JRuby on Android at JRubyConf.eu 2012

Uwe Kubosch

August 17, 2012
Tweet

More Decks by Uwe Kubosch

Other Decks in Programming

Transcript

  1. View Slide

  2. Ruboto
    JRuby on Android

    View Slide

  3. Uwe Kubosch
    Work at Datek Wireless in
    Norway
    Ruboto core developer
    JRuby rookie committer

    View Slide

  4. Ruboto?
    Builds on JRuby and
    Android
    Application and
    component generators
    Compact GUI definition
    Rake based development
    Test framework

    View Slide

  5. Topics covered
    History
    Ruboto IRB
    Installation & development
    tools
    Hello world!
    SpyCam
    Limitations
    Roadmap

    View Slide

  6. Activity: A screen
    View: A screen component
    Service: Background process
    Intent: Definition of action
    BroadcastReceiver: Listener for Intents
    Android basics/terms

    View Slide

  7. History 2009
    PoC by Charles Nutter
    (headius) february 24, 2009
    ruboto-irb by headius
    august 1, 2009

    View Slide

  8. History 2009
    PoC by Charles Nutter
    (headius) february 24, 2009
    ruboto-irb by headius
    august 1, 2009

    View Slide

  9. History 2009
    PoC by Charles Nutter
    (headius) february 24, 2009
    ruboto-irb by headius
    august 1, 2009

    View Slide

  10. History 2009
    PoC by Charles Nutter
    (headius) february 24, 2009
    ruboto-irb by headius
    august 1, 2009

    View Slide

  11. History 2009
    PoC by Charles Nutter
    (headius) february 24, 2009
    ruboto-irb by headius
    august 1, 2009

    View Slide

  12. Demo: OpenGL

    View Slide

  13. History 2010
    ruboto-core : GSoC 2010 by Daniel Jackoway
    Version 0.0.3 released december 19, 2010

    View Slide

  14. History 2011
    Testing framework: Feb 13,
    2011 (my first contribution)
    Bundler support: may 21,
    2011
    New Logo & Icons by
    RedNifre: july 20, 2011
    RubotoCore platform
    package: august 2011
    Rename to just “ruboto”:
    december 24, 2011

    View Slide

  15. History 2011
    Testing framework: Feb 13,
    2011 (my first contribution)
    Bundler support: may 21,
    2011
    New Logo & Icons by
    RedNifre: july 20, 2011
    RubotoCore platform
    package: august 2011
    Rename to just “ruboto”:
    december 24, 2011

    View Slide

  16. History 2012
    On-device generation of subclasses may 10,
    2012
    Class oriented component definition, 2012

    View Slide

  17. History 2012
    On-device generation of subclasses may 10,
    2012
    Class oriented component definition, 2012
    require  'ruboto/generate'
    ruboto_generate_widget(android.widget.EditText  =>  "your.package.RubotoEditText")
    @edit_script  =  ruboto_edit_text(:text  =>  ‘Hello!’)
    @edit_script.initialize_ruboto_callbacks  do
       def  on_draw(canvas)
           #  Do  Something
       end
    end

    View Slide

  18. History 2012
    On-device generation of subclasses may 10,
    2012
    Class oriented component definition, 2012

    View Slide

  19. History 2012
    On-device generation of subclasses may 10,
    2012
    Class oriented component definition, 2012
    $activity.handle_create do |bundle|
    setTitle ‘Hello World!’
    setup_content do
    linear_layout :orientation => LinearLayout::VERTICAL do
    @text_view = text_view :text => 'What hath Matz wrought?'
    button :text => ‘Click me!’, :width => :wrap_content, :id => 43
    end
    end
    handle_click do |view|
    if view.id == 43
    @text_view.setText 'What hath Matz wrought!'
    toast 'Flipped a bit via butterfly'
    end
    end
    end

    View Slide

  20. History 2012
    On-device generation of subclasses may 10,
    2012
    Class oriented component definition, 2012
    $activity.handle_create do |bundle|
    setTitle ‘Hello World!’
    setup_content do
    linear_layout :orientation => LinearLayout::VERTICAL do
    @text_view = text_view :text => 'What hath Matz wrought?'
    button :text => ‘Click me!’, :width => :wrap_content, :id => 43
    end
    end
    handle_click do |view|
    if view.id == 43
    @text_view.setText 'What hath Matz wrought!'
    toast 'Flipped a bit via butterfly'
    end
    end
    end
    $activity.start_ruboto_activity do
    def on_create(bundle)
    setTitle ‘Hello World!’
    click_handler = proc do |view|
    @text_view.setText 'What hath Matz wrought!'
    toast 'Flipped a bit via butterfly'
    end
    self.content_view =
    linear_layout :orientation => LinearLayout::VERTICAL do
    @text_view = text_view :text => 'What hath Matz wrought?'
    button :text => ‘Click me!, :width => :wrap_content,
    :on_click_listener => click_handler
    end
    end
    end

    View Slide

  21. History 2012
    On-device generation of subclasses may 10,
    2012
    Class oriented component definition, 2012
    $activity.handle_create do |bundle|
    setTitle ‘Hello World!’
    setup_content do
    linear_layout :orientation => LinearLayout::VERTICAL do
    @text_view = text_view :text => 'What hath Matz wrought?'
    button :text => ‘Click me!’, :width => :wrap_content, :id => 43
    end
    end
    handle_click do |view|
    if view.id == 43
    @text_view.setText 'What hath Matz wrought!'
    toast 'Flipped a bit via butterfly'
    end
    end
    end
    $activity.start_ruboto_activity do
    def on_create(bundle)
    setTitle ‘Hello World!’
    click_handler = proc do |view|
    @text_view.setText 'What hath Matz wrought!'
    toast 'Flipped a bit via butterfly'
    end
    self.content_view =
    linear_layout :orientation => LinearLayout::VERTICAL do
    @text_view = text_view :text => 'What hath Matz wrought?'
    button :text => ‘Click me!, :width => :wrap_content,
    :on_click_listener => click_handler
    end
    end
    end
    class ImageButtonActivity
    def on_create(bundle)
    set_title ‘Hello World!’
    click_handler = proc do |view|
    @text_view.setText 'What hath Matz wrought!'
    toast 'Flipped a bit via butterfly'
    end
    self.content_view =
    linear_layout :orientation => :vertical do
    @text_view = text_view :text => 'What hath Matz wrought?'
    button :text => ‘Click me!’, :width => :wrap_content, :id => 43,
    :on_click_listener => click_handler
    end
    end
    end

    View Slide

  22. Installation
    A Ruby implementation:
    Ruby 1.8.7, Ruby 1.9.3, JRuby, and Rubinius supported.
    Java JDK
    Apache ANT
    Android SDK
    [sudo] gem install ruboto
    Put all these in your PATH

    View Slide

  23. Tooling
    The “ruboto” command
    Rake

    View Slide

  24. Tooling - create project
    ruboto gen app --package my.cool.super_app

    View Slide

  25. Tooling - create project
    The “ruboto” command
    ruboto gem app --package my.cool.
    Rake based
    $ ruboto gen app --package my.cool.super_app
    Generating Android app SuperApp in /Users/uwe/workspace/jruby/super_app...
    ...
    Added file super_app/src/my/cool/super_app/SuperAppActivity.java
    ...
    Added file super_app/res/values/strings.xml
    Added file super_app/res/layout/main.xml
    Added file super_app/AndroidManifest.xml
    Added file super_app/build.xml
    Added file super_app/proguard-project.txt
    Removed file src/my/cool/super_app/SuperAppActivity.java
    Removed file res/layout/main.xml
    ...
    Added file /Users/uwe/workspace/jruby/super_app/src/my/cool/super_app/SuperAppActivity.java.
    Added file /Users/uwe/workspace/jruby/super_app/src/super_app_activity.rb.
    Added file /Users/uwe/workspace/jruby/super_app/test/src/super_app_activity_test.rb.

    View Slide

  26. Tooling - create component
    ruboto gen class Activity --name MyActivity

    View Slide

  27. Tooling - create component
    ruboto gen class Activity --name MyActivity
    $ ruboto gen class Activity --name MyActivity
    Added file /Users/uwe/workspace/jruby/hello_world/src/presentation/hello_world/MyActivity.java.
    Added file /Users/uwe/workspace/jruby/hello_world/src/my_activity.rb.
    Added file /Users/uwe/workspace/jruby/hello_world/test/src/my_activity_test.rb.
    Added activity to manifest.

    View Slide

  28. Tooling - build APK
    rake debug
    rake release

    View Slide

  29. Tooling - Install and run APK
    rake install
    rake start
    rake install start
    rake update_scripts:restart

    View Slide

  30. Questions?

    View Slide

  31. Hello World!

    View Slide

  32. Hello world!

    View Slide

  33. Hello world!
    $ android create project --target android-8 --path hello_world --package presentation.hello_world --activity HelloWorldActivity
    Generates file src/presentation/HelloWorldActivity.java

    View Slide

  34. Hello world!
    $ android create project --target android-8 --path hello_world --package presentation.hello_world --activity HelloWorldActiv
    Generates file src/presentation/HelloWorldActivity.java

    View Slide

  35. Hello world!
    $ android create project --target android-8 --pat...
    Generates file src/presentation/HelloWorldActivity.java
    import android.app.Activity;
    import android.os.Bundle;
    import android.widget.TextView;
    class HelloWorldActivity extends Activity {
    public void onCreate(Bundle bundle) {
    TextView t = new TextView(this);
    t.setText(“Hello World!”);
    setContentView(t);
    }
    }
    $ android create project --target android-8 --pat...
    Generates file src/presentation/HelloWorldActivity.java
    import android.app.Activity;
    import android.os.Bundle;
    import android.widget.TextView;
    class HelloWorldActivity extends Activity {
    public void onCreate(Bundle bundle) {
    TextView t = new TextView(this);
    t.setText(“Hello World!”);
    setContentView(t);
    }
    }

    View Slide

  36. Hello world!
    $ android create project --target android-8 --pat...
    Generates file src/presentation/HelloWorldActivity.java
    import android.app.Activity;
    import android.os.Bundle;
    import android.widget.TextView;
    class HelloWorldActivity extends Activity {
    public void onCreate(Bundle bundle) {
    TextView t = new TextView(this);
    t.setText(“Hello World!”);
    setContentView(t);
    }
    }
    $ android create project --target android-8 --pat...
    Generates file src/presentation/HelloWorldActivity.java
    import android.app.Activity;
    import android.os.Bundle;
    import android.widget.TextView;
    class HelloWorldActivity extends Activity {
    public void onCreate(Bundle bundle) {
    TextView t = new TextView(this);
    t.setText(“Hello World!”);
    setContentView(t);
    }
    }

    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical"
    android:gravity="center_horizontal|center_vertical"
    >
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Hello World!" />

    View Slide

  37. Hello world!
    $ android create project --target android-8 --pat...
    Generates file src/presentation/HelloWorldActivity.java
    import android.app.Activity;
    import android.os.Bundle;
    import android.widget.TextView;
    class HelloWorldActivity extends Activity {
    public void onCreate(Bundle bundle) {
    TextView t = new TextView(this);
    t.setText(“Hello World!”);
    setContentView(t);
    }
    }
    $ android create project --target android-8 --pat...
    Generates file src/presentation/HelloWorldActivity.java
    import android.app.Activity;
    import android.os.Bundle;
    import android.widget.TextView;
    class HelloWorldActivity extends Activity {
    public void onCreate(Bundle bundle) {
    TextView t = new TextView(this);
    t.setText(“Hello World!”);
    setContentView(t);
    }
    }

    View Slide

  38. Hello world!
    $ android create project --target android-8 --pat...
    Generates file src/presentation/HelloWorldActivity.java
    import android.app.Activity;
    import android.os.Bundle;
    import android.widget.TextView;
    class HelloWorldActivity extends Activity {
    public void onCreate(Bundle bundle) {
    TextView t = new TextView(this);
    t.setText(“Hello World!”);
    setContentView(t);
    }
    }
    $ android create project --target android-8 --pat...
    Generates file src/presentation/HelloWorldActivity.java
    import android.app.Activity;
    import android.os.Bundle;
    import android.widget.TextView;
    class HelloWorldActivity extends Activity {
    public void onCreate(Bundle bundle) {
    TextView t = new TextView(this);
    t.setText(“Hello World!”);
    setContentView(t);
    }
    }

    View Slide

  39. Hello world!
    $ android create project --target android-8 --pat...
    Generates file src/presentation/HelloWorldActivity.java
    import android.app.Activity;
    import android.os.Bundle;
    import android.widget.TextView;
    class HelloWorldActivity extends Activity {
    public void onCreate(Bundle bundle) {
    TextView t = new TextView(this);
    t.setText(“Hello World!”);
    setContentView(t);
    }
    }
    $ android create project --target android-8 --pat...
    Generates file src/presentation/HelloWorldActivity.java
    import android.app.Activity;
    import android.os.Bundle;
    import android.widget.TextView;
    class HelloWorldActivity extends Activity {
    public void onCreate(Bundle bundle) {
    TextView t = new TextView(this);
    t.setText(“Hello World!”);
    setContentView(t);
    }
    }

    View Slide

  40. Hello world!
    $ android create project --target android-8 --pat...
    Generates file src/presentation/HelloWorldActivity.java
    import android.app.Activity;
    import android.os.Bundle;
    import android.widget.TextView;
    class HelloWorldActivity extends Activity {
    public void onCreate(Bundle bundle) {
    TextView t = new TextView(this);
    t.setText(“Hello World!”);
    setContentView(t);
    }
    }
    $ android create project --target android-8 --pat...
    Generates file src/presentation/HelloWorldActivity.java
    import android.app.Activity;
    import android.os.Bundle;
    import android.widget.TextView;
    class HelloWorldActivity extends Activity {
    public void onCreate(Bundle bundle) {
    TextView t = new TextView(this);
    t.setText(“Hello World!”);
    setContentView(t);
    }
    }
    $ ruboto gen app --package presentation.hello_world
    Generates file src/hello_world_activity.rb

    View Slide

  41. Hello world!
    $ android create project --target android-8 --pat...
    Generates file src/presentation/HelloWorldActivity.java
    import android.app.Activity;
    import android.os.Bundle;
    import android.widget.TextView;
    class HelloWorldActivity extends Activity {
    public void onCreate(Bundle bundle) {
    TextView t = new TextView(this);
    t.setText(“Hello World!”);
    setContentView(t);
    }
    }
    $ android create project --target android-8 --pat...
    Generates file src/presentation/HelloWorldActivity.java
    import android.app.Activity;
    import android.os.Bundle;
    import android.widget.TextView;
    class HelloWorldActivity extends Activity {
    public void onCreate(Bundle bundle) {
    TextView t = new TextView(this);
    t.setText(“Hello World!”);
    setContentView(t);
    }
    }
    $ ruboto gen app --package presentation.hello_world
    Generates file src/hello_world_activity.rb

    View Slide

  42. Hello world!
    $ ruboto gen app --package presentation.hello_world
    Generates file src/hello_world_activity.rb
    import android.app.Activity;
    import android.os.Bundle;
    import android.widget.TextView;
    class HelloWorldActivity extends Activity {
    public void onCreate(Bundle bundle) {
    TextView t = new TextView(this);
    t.setText(“Hello World!”);
    setContentView(t);
    }
    }
    $ android create project --target android-8 --pat...
    Generates file src/presentation/HelloWorldActivity.java
    import android.app.Activity;
    import android.os.Bundle;
    import android.widget.TextView;
    class HelloWorldActivity extends Activity {
    public void onCreate(Bundle bundle) {
    TextView t = new TextView(this);
    t.setText(“Hello World!”);
    setContentView(t);
    }
    }

    View Slide

  43. Hello world!
    $ ruboto gen app --package presentation.hello_world
    Generates file src/hello_world_activity.rb
    import android.app.Activity;
    import android.widget.TextView;
    class HelloWorldActivity extends Activity
    def onCreate( bundle)
    t = new TextView(this);
    t.setText(“Hello World!”);
    setContentView(t);
    end
    end
    $ android create project --target android-8 --pat...
    Generates file src/presentation/HelloWorldActivity.java
    import android.app.Activity;
    import android.os.Bundle;
    import android.widget.TextView;
    class HelloWorldActivity extends Activity {
    public void onCreate(Bundle bundle) {
    TextView t = new TextView(this);
    t.setText(“Hello World!”);
    setContentView(t);
    }
    }

    View Slide

  44. Hello world!
    $ ruboto gen app --package presentation.hello_world
    Generates file src/hello_world_activity.rb
    import android.app.Activity;
    import android.widget.TextView;
    class HelloWorldActivity extends Activity
    def onCreate( bundle)
    t = TextView.new(this);
    t.setText(“Hello World!”);
    setContentView(t);
    end
    end
    $ android create project --target android-8 --pat...
    Generates file src/presentation/HelloWorldActivity.java
    import android.app.Activity;
    import android.os.Bundle;
    import android.widget.TextView;
    class HelloWorldActivity extends Activity {
    public void onCreate(Bundle bundle) {
    TextView t = new TextView(this);
    t.setText(“Hello World!”);
    setContentView(t);
    }
    }

    View Slide

  45. Hello world!
    $ ruboto gen app --package presentation.hello_world
    Generates file src/hello_world_activity.rb
    import android.app.Activity;
    import android.widget.TextView;
    class HelloWorldActivity extends Activity
    def onCreate( bundle)
    t = TextView.new(self);
    t.setText(“Hello World!”);
    setContentView(t);
    end
    end
    $ android create project --target android-8 --pat...
    Generates file src/presentation/HelloWorldActivity.java
    import android.app.Activity;
    import android.os.Bundle;
    import android.widget.TextView;
    class HelloWorldActivity extends Activity {
    public void onCreate(Bundle bundle) {
    TextView t = new TextView(this);
    t.setText(“Hello World!”);
    setContentView(t);
    }
    }

    View Slide

  46. Hello world!
    $ ruboto gen app --package presentation.hello_world
    Generates file src/hello_world_activity.rb
    import android.app.Activity;
    import android.widget.TextView;
    class HelloWorldActivity < Activity
    def onCreate( bundle)
    t = TextView.new(self);
    t.setText(“Hello World!”);
    setContentView(t);
    end
    end
    $ android create project --target android-8 --pat...
    Generates file src/presentation/HelloWorldActivity.java
    import android.app.Activity;
    import android.os.Bundle;
    import android.widget.TextView;
    class HelloWorldActivity extends Activity {
    public void onCreate(Bundle bundle) {
    TextView t = new TextView(this);
    t.setText(“Hello World!”);
    setContentView(t);
    }
    }

    View Slide

  47. Hello world!
    $ ruboto gen app --package presentation.hello_world
    Generates file src/hello_world_activity.rb
    import android.app.Activity
    import android.widget.TextView
    class HelloWorldActivity < Activity
    def onCreate( bundle)
    t = TextView.new(self)
    t.setText(“Hello World!”)
    setContentView(t)
    end
    end
    $ android create project --target android-8 --pat...
    Generates file src/presentation/HelloWorldActivity.java
    import android.app.Activity;
    import android.os.Bundle;
    import android.widget.TextView;
    class HelloWorldActivity extends Activity {
    public void onCreate(Bundle bundle) {
    TextView t = new TextView(this);
    t.setText(“Hello World!”);
    setContentView(t);
    }
    }

    View Slide

  48. Hello world!
    $ ruboto gen app --package presentation.hello_world
    Generates file src/hello_world_activity.rb
    import android.widget.TextView
    class HelloWorldActivity
    def onCreate( bundle)
    t = TextView.new(self)
    t.setText(“Hello World!”)
    setContentView(t)
    end
    end
    $ android create project --target android-8 --pat...
    Generates file src/presentation/HelloWorldActivity.java
    import android.app.Activity;
    import android.os.Bundle;
    import android.widget.TextView;
    class HelloWorldActivity extends Activity {
    public void onCreate(Bundle bundle) {
    TextView t = new TextView(this);
    t.setText(“Hello World!”);
    setContentView(t);
    }
    }

    View Slide

  49. Hello world!
    $ ruboto gen app --package presentation.hello_world
    Generates file src/hello_world_activity.rb
    import android.widget.TextView
    class HelloWorldActivity
    def onCreate(bundle)
    t = TextView.new(self)
    t.setText(“Hello World!”)
    setContentView(t)
    end
    end
    $ android create project --target android-8 --pat...
    Generates file src/presentation/HelloWorldActivity.java
    import android.app.Activity;
    import android.os.Bundle;
    import android.widget.TextView;
    class HelloWorldActivity extends Activity {
    public void onCreate(Bundle bundle) {
    TextView t = new TextView(this);
    t.setText(“Hello World!”);
    setContentView(t);
    }
    }

    View Slide

  50. Hello world!
    $ ruboto gen app --package presentation.hello_world
    Generates file src/hello_world_activity.rb
    import android.widget.TextView
    class HelloWorldActivity
    def on_create(bundle)
    t = TextView.new(self)
    t.text = “Hello World!”
    setContentView(t)
    end
    end
    $ android create project --target android-8 --pat...
    Generates file src/presentation/HelloWorldActivity.java
    import android.app.Activity;
    import android.os.Bundle;
    import android.widget.TextView;
    class HelloWorldActivity extends Activity {
    public void onCreate(Bundle bundle) {
    TextView t = new TextView(this);
    t.setText(“Hello World!”);
    setContentView(t);
    }
    }

    View Slide

  51. Hello world!
    $ ruboto gen app --package presentation.hello_world
    Generates file src/hello_world_activity.rb
    ruboto_import_widget :TextView
    class HelloWorldActivity
    def on_create(bundle)
    t = text_view text: ‘Hello World!'
    setContentView(t)
    end
    end
    $ android create project --target android-8 --pat...
    Generates file src/presentation/HelloWorldActivity.java
    import android.app.Activity;
    import android.os.Bundle;
    import android.widget.TextView;
    class HelloWorldActivity extends Activity {
    public void onCreate(Bundle bundle) {
    TextView t = new TextView(this);
    t.setText(“Hello World!”);
    setContentView(t);
    }
    }

    View Slide

  52. Hello world!
    $ ruboto gen app --package presentation.hello_world
    Generates file src/hello_world_activity.rb
    ruboto_import_widget :TextView
    class HelloWorldActivity
    def on_create(bundle)
    setContentView(text_view text: ‘Hello World!')
    end
    end
    $ android create project --target android-8 --pat...
    Generates file src/presentation/HelloWorldActivity.java
    import android.app.Activity;
    import android.os.Bundle;
    import android.widget.TextView;
    class HelloWorldActivity extends Activity {
    public void onCreate(Bundle bundle) {
    TextView t = new TextView(this);
    t.setText(“Hello World!”);
    setContentView(t);
    }
    }

    View Slide

  53. Questions?

    View Slide

  54. Examples
    Make a call
    Show webpage
    Spycam

    View Slide

  55. Display a web page
    import "android.content.Intent"
    import "android.net.Uri"
    class RubotoHomePageActivity
    def on_resume
    intent = Intent.new(Intent::ACTION_VIEW)
    uri = Uri.parse("http://ruboto.org/")
    intent.setData(uri)
    startActivity(intent)
    end
    end

    View Slide

  56. Phone home
    import "android.content.Intent"
    import "android.net.Uri"
    class PhoneHomeActivity
    def on_resume
    intent = Intent.new(Intent::ACTION_CALL)
    uri = Uri.parse("tel:5551234")
    intent.setData(uri)
    startActivity(intent)
    end
    end

    View Slide

  57. Spycam
    Start a WEBrick web server
    Access the camera

    View Slide

  58. Spycam
    Start a WEBrick web server
    Access the camera
    require  'monitor'
    require  'camera_helper'
    require  'ruboto/util/stack'
    class  SpycamServer
       extend  MonitorMixin
       PORT  =  4567
       DOC_ROOT  =  "#{$activity.files_dir.absolute_path}/"
       @@server  =  nil
       def  self.start(activity,  server_status_view)
           Thread.with_large_stack(512)  do
               synchronize  do
                   if  @@server.nil?
                       activity.run_on_ui_thread  {  server_status_view.text  =  
    "Loading"  }
                       require  'webrick'
                       activity.run_on_ui_thread  {  server_status_view.text  =  
    "Loaded"  }
                       @@server  =  WEBrick::HTTPServer.new(:Port  =>  
    PORT,  :DocumentRoot  =>  DOC_ROOT)
                       @@server.mount_proc('/')  do  |req,  resp|
                           case  req.path
                           when  '/',  'index.html'
                               CameraHelper.take_picture(activity)
                               resp.content_type  =  "text/html"
                               resp.body  =  '
                                                               
                                                                   Spycam
                                                               
                                                               
                                                                   
                                                               
                                                           '
                               raise  WEBrick::HTTPStatus::OK
                           when  '/latest.jpg'
                               resp.content_type  =  "image/jpg"
                               resp.body  =  $camera_data
                               $camera_data  =  nil
                               raise  WEBrick::HTTPStatus::OK
                           else
                               resp.body  =  "Unknown  path:  #{req.path.inspect}"
                               raise  WEBrick::HTTPStatus::NotFound
                           end
                       end
                       server  =  @@server
                       Thread.new{server.start}
    require  'ruboto/activity'
    require  'ruboto/widget'
    require  'spycam_server'
    import  android.util.Log
    import  android.view.Surface
    import  android.view.WindowManager
    ruboto_import_widgets  :Button,  :LinearLayout,  :ScrollView,  :TextView
    ruboto_import_widget  :SurfaceView,  "android.view"
    class  SpycamActivity
       def  on_create(bundle)
           rotation  =  {
                   Surface::ROTATION_0  =>  0,Surface::ROTATION_90  =>  
    90,Surface::ROTATION_180  =>  180,Surface::ROTATION_270  =>  270
           }[window_manager.default_display.rotation]
           self.title  =  "Spycam  #{rotation}"
           #  
    self.setRequestedOrientation(android.content.pm.ActivityInfo::SCREEN_OR
    IENTATION_PORTRAIT)
           window.add_flags(WindowManager::LayoutParams::FLAG_KEEP_SCREEN_ON)
           setContentView(linear_layout(:orientation  =>  :vertical)  do
               linear_layout  do
                   text_view  :text  =>  "Server:  "
                   @server_status_view  =  text_view
               end
               linear_layout  do
                   text_view  :text  =>  "Picture:  "
                   @camera_status_view  =  text_view
               end
               sv  =  surface_view
               sv.holder.add_callback  RubotoSurfaceHolderCallback.new(rotation)
               #  Deprecated,  but  still  required  for  older  API  version
               sv.holder.set_type  
    android.view.SurfaceHolder::SURFACE_TYPE_PUSH_BUFFERS
           end)
       end
       
       def  set_camera_status(value)
           @camera_status_view.text  =  value
       end
       def  camera_status=(value)
           run_on_ui_thread  {  $activity.set_camera_status  value  }
       end
       def  on_resume  
    class  CameraHelper
       def  self.take_picture(activity)
           activity.camera_status  =  "Set  volume..."
           am  =  
    activity.getSystemService(android.content.Context::AUDIO_SERVICE)
           old_volume  =  
    am.get_stream_volume(android.media.AudioManager::STREAM_SYSTEM)
           am.set_stream_volume(android.media.AudioManager::STREAM_SYSTEM,  0,  
    0)
           activity.camera_status  =  "Taking  picture..."
           picture_taken  =  false
           $camera.take_picture(nil,  nil)  do  |data,  camera|
               $camera_data  =  String.from_java_bytes(data)
               activity.camera_status  =  "Gotcha!"
               $camera.start_preview
               am.set_stream_volume(android.media.AudioManager::STREAM_SYSTEM,  
    old_volume,  0)
               picture_taken  =  true
           end
           sleep  0.1  until  picture_taken
       end
    end

    View Slide

  59. Demo: Spycam

    View Slide

  60. Limitations
    Ruby class cannot directly
    subclass Java class
    Tiny stack on main thread
    Startup time
    Runtime size
    No AOT/JIT compilation

    View Slide

  61. Status
    Ruboto is in production!
    Almost monthly releases.
    Still improving the API
    Support Android 2.1 - 4.1
    5 active developers, more welcome!

    View Slide

  62. Roadmap
    1.0.0 release this year?
    Dalvik backend for the IR compiler
    Direct subclassing of Java classes
    AOT Compilation / IR Persistence
    Mirah integration ( http://www.mirah.org )
    FFI support
    Eclipse plugin

    View Slide

  63. Contributors welcome!
    ruboto.org

    View Slide

  64. Questions?

    View Slide

  65. Thank you!

    View Slide