Skip to content

Commit

Permalink
Complete initial version of the HOWTO
Browse files Browse the repository at this point in the history
  • Loading branch information
castaway committed Dec 14, 2012
1 parent 7388573 commit 0bc0292
Showing 1 changed file with 57 additions and 8 deletions.
65 changes: 57 additions & 8 deletions HOWTO.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,29 @@ HowTo use Object-Remote-Java (JavaBridge) with Perl on Android
Object::Remote
--------------

Object::Remote is a Perl module which can be used to run your Perl program or script on a remote host and return the results, without needing to run any install steps. It does this by implementing a JSON based protocol. Instead of sending objects or coderefs around, it stores an each with an id at both ends of the conversation, and just indicates the id to the other end.
[Object::Remote][0] is a Perl module which can be used to run your Perl program or script on a remote host and return the results, without needing to run any install steps. It does this by implementing a JSON based protocol. Instead of sending objects or coderefs around, it stores an each with an id at both ends of the conversation, and just indicates the id to the other end.

Objects can be created, and methods called. The results are returned as either simple scalar data, or as IDs of the results, which can be further queried. All this detail is hidden to the actual user, so we can just treat objects as local.

Object::Remote will also transport modules from one Perl host to the other (including those necessary to run itself), so backend hosts only need an installation of Perl (of v5.8.1 and above).

I'm told there will be a CPAN release of Object::Remote Real Soon Now(tm).

Object-Remote-Java
------------------

Object::Remote Connections can be made via SSH, to an instance of Perl installed on the remote host. In order to allow a connection to a non-Perl backend, we have added a patch to allow the protocol to be spoken over a straight TCP connection. As Java is not interpreted, the Java based backend comes as a prebuilt application, that needs to be started on the remote host.
Object::Remote Connections can be made via SSH, to an instance of Perl installed on the remote host. In order to allow a connection to a non-Perl backend, we have added a patch to allow the protocol to be spoken over a straight TCP connection. As Java is not interpreted, the Java based backend comes as a prebuilt application, that needs to be started on the remote host. It can also be subclassed to include in your own application. Object-Remote-Java is [on github][object-remote-java-github].

Android specifics
-----------------

To run Object-Remote-Java on Android, we also packaged it as an .apk file (Android Package). You can also subclass the main [Activity][android-activity] if you wish to add functionality to it. The [RunPerl][run-perl] application does this, and also bundles a copy of Perl.
To run Object-Remote-Java on Android, we also packaged it as an .apk file (Android Package), called JavaBridge [which you can download from box.net here][java-bridge-download] You can also subclass the main [Activity][android-activity] if you wish to add functionality to it. The [RunPerl][run-perl] application does this, and also bundles a copy of Perl. [Download a pre-built copy here][run-perl-download].

You can run the Perl script either on Android itself (using RunPerl or sl4a or however you like), or, as this is over TCP, from another host.

To use Android rather than plain Java, there are a few caveats:

* You cannot update the GUI (create new UI controls etc) from outside of the thread that initially created the GUI. We provide a way to do this, see below.
* You [cannot update the GUI][main-thread] (create new UI controls etc) from outside of the thread that initially created the GUI. We provide a way to do this, see below.

The examples below are Android specific, with links to the Android developer documentation.

Expand All @@ -43,7 +45,7 @@ Initial connection
Create a connection object which will be used to communicate between Perl and Java. The Java side listens on port 9849:

use Object::Remote::Connector::TCP;
my $conn = Object::Remote->connect('tcp://192.168.1.2:9849/');
my $conn = Object::Remote->connect('tcp://10.1.1.1:9849/');


Functions / Static methods
Expand Down Expand Up @@ -96,16 +98,63 @@ Interfaces, Coderefs/Callbacks

In order to implement callbacks, for example the event code that runs when a user clicks a button in the UI, usually in Java you need to create a new class as which implements an interface. Object-Remote-Java provides a class which implemetns the interface for you, using a Proxy and Invocation Handler. For this we need to know what the inner class name of the interface is. For example, 'android.view.View.OnClickListener' means the inner class 'OnClickListener' in the 'android.view.View' class. To create the new instance:

my $button_event_listener = uk::me::desert_island::theorbtwo::bridge::InterfaceImplementor->can::on($conn, 'make_instance')->('android.view.View$OnClickListener', $button_click_event);
Write a code reference containing the code to run, this will get called for every method invocation on your handler, that isn't a basic Object method:

my $button_click_event = sub {
my ($invocation_handler, $this, $method_info, $args) = @_;
my ($method, $decl_class, $short_name, $long_name) = @$method_info;
if($method_name eq 'onClick') {
print "I was clicked!\n";
}
};

Create an interface creator, this is a static method on a special java bridge class:

my $interface_creator = uk::me::desert_island::theorbtwo::bridge::InterfaceImplementor->can::on($conn, 'make_instance');

Create the interface subclass and assign the code reference to be called:

my $button_event_listener = $interface_creator->('android.view.View$OnClickListener', $button_click_event);

Then tell the control to use the new listener:

Interfaces
----------
$button->setOnClickListener($button_event_listener);

my $button_event_listener = uk::me::desert_island::theorbtwo::bridge::InterfaceImplementor->can::on($conn, 'make_instance')->('android.view.View$OnClickListener', $button_click_event);

The code reference will be wrapped in a [Runnable][runnable] on the Java side.

Updating the GUI
----------------

As mentioned above, in order to actually change the UI on the Android application, you need to run code in the same thread that the original UI was created from. Luckily the API provides us a method to do this "runOnUiThread", an Activity method. We can't pass it a code reference to call, as these run in their own threads. Currently we need to make a new single-method Runnable, and ask the Activity to call it:

my $update_text = uk::me::desert_island::theorbtwo::bridge::MethodCallRunnable->new::on($conn, $edit_text, 'setText', [$file_content]);
$activity->runOnUiThread($update_text);

The upside of this is that it need to doesn't call back to the Perl layer in order to actually run. The downside is that so far it supports just one method call.

Activity events
---------------

There are a number of events that normally one would implement as methods in the Activity class itself. We have added stub methods, which will pull the actual Runnables to call out of a HashMap (which is similar to a Perl hash). Currently this covers "[onActivityResult][onactivityresult]", needed to respond to the result of a async activity, and "[onConfigurationChanged][onconfigurationchanged]" for responding to a screen rotation or similar.

To set these, call the "setEventCallbacks" method with a HashMap:

my $callbacks = java::util::HashMap->new::on($conn);
$callbacks.put('on_activity_result', sub { ... });
$activity->setEventCallbacks($callbacks);



[0]: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?p=scpubgit/Object-Remote.git
[android-activity]: http://developer.android.com/guide/components/activities.html
[run-perl]: https://github.com/castaway/run-perl
[main-thread]: http://developer.android.com/guide/components/processes-and-threads.html#Threads
[runnable]: http://developer.android.com/reference/java/lang/Runnable.html
[java-bridge-download]: https://www.box.com/s/c9p4yq3fdidpywnshi0c
[object-remote-github]: https://github.com/theorbtwo/Object-Remote-Java
[run-perl-download]: https://www.box.com/s/pbc1xcd6n88cykdomdh6
[onactivityresult]: http://developer.android.com/reference/android/app/Activity.html#onActivityResult(int, int, android.content.Intent)
[onconfigurationchanged]: http://developer.android.com/reference/android/app/Activity.html#onConfigurationChanged(android.content.res.Configuration)

0 comments on commit 0bc0292

Please sign in to comment.