Go for Android with native UI support

1,280 views
Skip to first unread message

s.sel...@gmail.com

unread,
Jan 19, 2015, 1:43:35 AM1/19/15
to golan...@googlegroups.com
Hello!

As far as I know, there is no way of working with Android UI directly from Go (without immersing yourself in Java) in current state of go-mobile.

So, I've started working on project, that will bring that to Go: https://github.com/seletskiy/go-android-rpc

Currently, it's just proof-of-concept; it sits on top of golang.org/x/mobile.

However, as you can see in example app in `main.go`, it's possible to create simple UI using Android SDK without touching any Java code in quite well Go code. What you can see in `main.go` was tested on real device.

I'm wondering, will it ever be transparent Java-Go object passing in some foreseeable future? I hope so.

David Crawshaw

unread,
Jan 20, 2015, 6:44:21 AM1/20/15
to s.sel...@gmail.com, golang-nuts
In the original proposal for Go Android support,
http://golang.org/s/go14android, I decided to avoid generating Go
interfaces for the Android SDK for two reasons. The first is that I
don't think I can build idiomatic Go packages that present all of the
features in the SDK. (It will end up looking like Java.) The second
reason is we are interested in platform portability, and there are too
many non-overlapping features in mobile device APIs to create a common
set of libraries.

I suppose now I can add a third reason, which is just the simple
foundational work in x/mobile has turned out to be very involved. Good
support for iOS for what little is there is going to take a lot of
work. I'm not sure we have the hours to properly maintain anything
more.

That said, I think your project is very interesting and I hope you
keep working on it. One thing I noticed on a quick look through your
code: you may not realize that gobind will manage callbacks from Java
into Go. That is if your Go package defines:

type Callback interface {
CallJava(x T) U
}

func Register(c Callback) {
c.CallJava(x) // c can be stored for later use
}

Then in Java you can subclass the generated class and implement the
CallJava method:

public class J extends gopkg.Callback {
public CallJava(T x) U {
// code you want called from Go.
}
}
...
gopkg.Register(new J());

This may save you some of the bookkeeping you are doing in your android package.

Thank you for sharing your work.
> --
> You received this message because you are subscribed to the Google Groups
> "golang-nuts" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to golang-nuts...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

Stanislav Seletskiy

unread,
Jan 20, 2015, 7:44:04 AM1/20/15
to David Crawshaw, golang-nuts
Thanks for the reply!

Yes, we can generate numerous bindings using gobind, but I've decided
to use only one entry point from Go to Java to minimize amount of
generated code, so we can debug with easy.

One question, is there any plans for passing non-simple (arbitrary)
objects between Go and Java (especially from Java to Go)? I guess it's
nearly impossible to implement, but anyway.
--
Stanislav Seletskiy

David Crawshaw

unread,
Jan 20, 2015, 8:06:54 AM1/20/15
to Stanislav Seletskiy, golang-nuts
On Tue, Jan 20, 2015 at 7:43 AM, Stanislav Seletskiy
<s.sel...@gmail.com> wrote:
> One question, is there any plans for passing non-simple (arbitrary)
> objects between Go and Java (especially from Java to Go)? I guess it's
> nearly impossible to implement, but anyway.

The intention is to support all Go types, but with several limits on
how how data is copied and referenced across the language boundary. In
particular, a slice type will be copied, a *T will be a reference, and
a struct T will be treated as a *T.

One unfortunate limit of this approach is that a simple data structure
(for example type S struct { F1 int; F2 string }) will turn into a
reference type with methods GetF1, GetF2. Sometimes for performance on
Android you would prefer it to be copied into a similar Java class:

public class S {
public long F1;
public String F2;
}

However I suspect this will not be much of a problem, as even though
this is particularly useful and I do this frequently when programming
in Java, I find most Java programmers insist on hiding fields and
creating methods. That is, GetF1, SetF1. So the limit fits with common
Java style.

Stanislav Seletskiy

unread,
Jan 21, 2015, 6:47:34 AM1/21/15
to David Crawshaw, golang-nuts
Actually, I wanted to know, will be there a way to somehow pass
_existing_ Java objects to Go code? I mean not custom-class objects,
but SDK objects or other native Java objects? From my point of view it
far more important to be able to pass Java objects (like Views or
whatever) to Go and calling native (SDK) methods with predefined
non-simple types. I guess, that it is, probably, not possible due to
variety of types and different memory models.

However, as you are far more involved in the cross-language boundary
development, may I ask you about correctness of my hypothesis?
--
Stanislav Seletskiy

David Crawshaw

unread,
Jan 21, 2015, 8:57:50 AM1/21/15
to Stanislav Seletskiy, golang-nuts
I'm sure a cross-language abstraction that starts with Java and
produces Go is possible. The advantage with gobind starting from Go is
it can target multiple languages. It is designed primarily to make it
easy to write Go for multiple mobile platforms, some of which do not
use Java.

That said, I suspect you could build a general purpose Java Object
container with gobind. Something like:

type Object interface {
Type() string
Call(method string, args []Object) Object
}

and then on the Java side implement it as:

public final class Container extends pkg.Object {
public final Object obj;
public Container(Object o) { obj = o; }
public String Type() {
return obj.getClass().getCanonicalName();
}
public pkg.Object Call(String method, pkg.Object[] args) {
// reflect over obj and call method with args.
}
}

With gobind, if you pass an object reference from Java to Go and then
back to Java, it is designed to hand you back the original Java
object. That means it is possible in Container.Call to reach into each
element of args and extract the Java object, and using instanceof
casting to get the underlying data. (For example,
(String)(args[0].obj).)

There would also need to be helper Java methods on some standard
helper type for converting arbitrary Object instances on the Go side
back into Java.

On Wed, Jan 21, 2015 at 6:47 AM, Stanislav Seletskiy
Reply all
Reply to author
Forward
0 new messages