android externals

Moderators: FourthWorld, heatherlaine, Klaus, kevinmiller, LCMark

LCMark
Livecode Staff Member
Livecode Staff Member
Posts: 1209
Joined: Thu Apr 11, 2013 11:27 am

Re: android externals

Post by LCMark » Mon Jul 15, 2013 4:40 pm

pretty excited to see @runrevmark's latest commit... just compiled the test external and android engine... now I need to work out how to get the two together... runtime folder in user extensions? or is there a better way?
Judging by your subsequent comment I'm guessing you got it to work :)

The way I tested this out was to build (and run) the IDE Engine through Xcode (in debug mode), built the android engine (in debug mode - using the shell script), then just used a test stack with the lcext file for revtestexternal in Copy Files. The test stack can then be run in the Android emulator using the 'Test' button.

It was quite pleasing to see it working - although there is still a fair amount to do... The LC API Java bindings aren't complete, Java exceptions are ignored (they need to be caught in generated code), and some more type mapping shims are needed. This is of course, not even mentioning the building of the android externals which is currently through a rather specific shell script, nor the issues @monte raised about type specs in the lcidl file.

monte
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 1564
Joined: Fri Jan 13, 2012 1:47 am
Contact:

Re: android externals

Post by monte » Mon Jul 15, 2013 10:06 pm

Yep I got it to work. If your running a built IDE does that pull standalone engines from the build folder?

Since then I've been nutting away at seeing if I can get IDE support for the whole process. I've got ant building the jar, compiling the lcidl and calling ndk-build but it's rightly getting hung up on objective-c stuff in the mergPop lcidl that I'm using. I guess it's a tossup whether we change ldidlc to deal with this or I change my lcidl files but it does seem a shame to lose NSString to gain String...

In the long run I think the idea of a use {objective-c|java} on platform clause is the cleanest and most extensible.

I'm trying to make things as generic as possible so it can be reused but I'm having trouble with the proper LiveCode.h location in Application Support because of the space... ndk-build can't find it. So at the moment I'm relying on the user having a livecode repo in their home directory.
LiveCode User Group on Facebook : http://FaceBook.com/groups/LiveCodeUsers/

monte
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 1564
Joined: Fri Jan 13, 2012 1:47 am
Contact:

Re: android externals

Post by monte » Mon Jul 15, 2013 10:44 pm

Then the abstract types map depending on the 'on' clause:
objc - string -> NSString, data -> NSData, array -> NSArray, dictionary -> NSDictionary
java - string -> Java String, data -> byte[], array -> Java Array, dictionary -> Java hash table equivalent
c - string -> c-string, data -> c-data, array -> c-array, dictionary -> c-dictionary
Ah.. sorry, paging... I only saw the last post and not this one before my last answer. I guess the question is mainly if it's necessary to mix implementation languages per platform on an individual command level or if it's sufficient to implement a single use clause at the top?

One advantage might be if we extended these on clauses a bit...

Code: Select all

command foobar
    on ios, mac use objc
    on android use java
    on windows, linux throw "platform not supported"
    in a as string
and the less harsh option...

Code: Select all

command foobar
    on ios, mac use objc
    on android use java
    on windows, linux return "platform not supported"
    in a as string
I guess this throw on platform stuff could be implemented in addition to file wide use clauses. Can you see a use case for mixing implementation languages?

Regarding encoding it sounds like the best option for me is to wait until the modules interface does all this for me rather than come up with my own scheme ;-)
LiveCode User Group on Facebook : http://FaceBook.com/groups/LiveCodeUsers/

LCMark
Livecode Staff Member
Livecode Staff Member
Posts: 1209
Joined: Thu Apr 11, 2013 11:27 am

Re: android externals

Post by LCMark » Tue Jul 16, 2013 10:02 am

Yep I got it to work. If your running a built IDE does that pull standalone engines from the build folder?
Yes - if you run the IDE engine from within the build folder then the IDE will pick up all the binary components from the build folder. In particular, it will use Android and iOS engines for standalone building (and the 'Test' button). Note that at the moment the 'MODE' of the build is uniform - i.e. if you run a debug IDE engine, it will use debug standalone engines.
Since then I've been nutting away at seeing if I can get IDE support for the whole process. I've got ant building the jar, compiling the lcidl and calling ndk-build but it's rightly getting hung up on objective-c stuff in the mergPop lcidl that I'm using. I guess it's a tossup whether we change ldidlc to deal with this or I change my lcidl files but it does seem a shame to lose NSString to gain String...
I think we need to change lcidlc here - the suggestions we have been discussing I think will be more than fine for now (see below). Sounds like good progress on an easier way to build the android externals :)
I'm trying to make things as generic as possible so it can be reused but I'm having trouble with the proper LiveCode.h location in Application Support because of the space... ndk-build can't find it. So at the moment I'm relying on the user having a livecode repo in their home directory.
I must confess I still haven't come up with a reasonable way to deal with this. Having to 'install' files like LiveCode.h is a bit of a pain - particularly when it's evolving. I don't think people will mind having to checkout the LiveCode repo for now to develop externals - perhaps we should just tie the external building projects and makefiles etc. to a environment var pointing to a checked out repo. In the future this could perhaps change to a folder with the extracted bits just needed for external development.
I guess the question is mainly if it's necessary to mix implementation languages per platform on an individual command level or if it's sufficient to implement a single use clause at the top?
Well, I guess this depends on the external. If you imagine one which has some platform-specific commands, and some non-platform specific commands then it might be useful to be able to do so. Your suggestion of having an automatic 'platform not supported' result or exception does indicate that having some level of per-command configuration would be useful. However, it might be neater just to adjust the semantics of 'use' (or some variant) slightly - i.e. each handler picks up the current settings then you could do something like:

Code: Select all

use objc on ios, mac
use java on android
use none on windows, linux

command foobar in a as string

use c on all

command barfoo in a as string
This way you'd need to structure the lcidl file into blocks - but that has the advantage of handlers of a similar ilk all being together.

In terms of the 'none' (to indicate not supported), I'd advocate having it throw an error rather than return in the result as this fits with both commands and functions, and doesn't pollute the return values of them. Indeed, we could also make this case a special error code on the engine so the IDE could handle in perhaps a better way.

monte
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 1564
Joined: Fri Jan 13, 2012 1:47 am
Contact:

Re: android externals

Post by monte » Tue Jul 16, 2013 10:47 am

I like this plan because it handles what I think is the most likely use case of one implementation language per external well by only needing to define it once... I'm still struggling to think of a use case where you couldn't define the abstract types at the top then use the c types for your cross platform handlers though. I guess if we are thinking ahead to java on all platforms...
LiveCode User Group on Facebook : http://FaceBook.com/groups/LiveCodeUsers/

Sean O'Connor
Livecode Opensource Backer
Livecode Opensource Backer
Posts: 21
Joined: Sat Mar 16, 2013 7:06 pm

Re: android externals

Post by Sean O'Connor » Tue Jul 16, 2013 2:06 pm

Oh and there is another contender on the horizon. can you beleive mozilla OS!! its probably early days in the making but it seems to be gaining some traction with mobile manufacturers with a couple of devices already at market with the new os installeed...oops wrong place i'm in android dev. eeps. sorry folks.
when the going gets tough the tough get going.

monte
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 1564
Joined: Fri Jan 13, 2012 1:47 am
Contact:

Re: android externals

Post by monte » Wed Jul 17, 2013 2:42 am

FYI whenever I catch a spare minute (rare at the moment) I'm working on handling parameters in Post. Given we can only use objects I don't think the signature is necessary so I'm working on a solution that uses getName on the class then handles known classes. Unless anyone knows some va_list creation magic then I think this is the simplest thing to do.
LiveCode User Group on Facebook : http://FaceBook.com/groups/LiveCodeUsers/

LCMark
Livecode Staff Member
Livecode Staff Member
Posts: 1209
Joined: Thu Apr 11, 2013 11:27 am

Re: android externals

Post by LCMark » Wed Jul 17, 2013 6:30 pm

I like this plan because it handles what I think is the most likely use case of one implementation language per external well by only needing to define it once... I'm still struggling to think of a use case where you couldn't define the abstract types at the top then use the c types for your cross platform handlers though. I guess if we are thinking ahead to java on all platforms...
You raise a good point about use-case - although I guess my thinking here was cleaning up method definitions.

As currently posed 'java' is a prefix to commands and functions causing a direct-to-java shim to be generated for Android, and an expectation that there will be a native method in all other platforms. Allowing the 'use' clause to appear between handlers means that this isn't necessary any more:

Code: Select all

use java on android
command foobar in a as string 
use c on android
command barfoo in a as string
Would define a java foobar method (taking a java string) on Android, but a c foobar method on all platforms (taking a c-string) and a native barfoo method on all platforms (taking a c-string).

The point here is that this seems to make more sense for defining the type of method (whether it is in java or native code) than having a 'java' prefix that only makes any sense for Android and is ignored for the other platforms.

It also fits in better with the idea of being able to declare a method as not available on some platforms (the 'none' clause).

monte
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 1564
Joined: Fri Jan 13, 2012 1:47 am
Contact:

Re: android externals

Post by monte » Wed Jul 17, 2013 9:07 pm

yes it does resolve the quirky syntax on a few counts (java prefix, c parameters)
LiveCode User Group on Facebook : http://FaceBook.com/groups/LiveCodeUsers/

monte
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 1564
Joined: Fri Jan 13, 2012 1:47 am
Contact:

Re: android externals

Post by monte » Sun Jul 21, 2013 12:48 pm

Rainy day today so I found some time to get LCObjectPost/Send arguments working. So far it supports String,Boolean,Integer,Double and ByteBuffer. Not sure what to do about LC.Array because that would mean moving the argument parser into the interface generator...I guess we can worry about that when LC.Array is ready ;-)

The other one I guess is Dictionary but neither NSDictionary or NSArray are supported on iOS so it can wait too I guess.

Anyway, here you go: https://github.com/runrevmark/livecode/pull/3
LiveCode User Group on Facebook : http://FaceBook.com/groups/LiveCodeUsers/

monte
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 1564
Joined: Fri Jan 13, 2012 1:47 am
Contact:

Re: android externals

Post by monte » Sun Jul 21, 2013 9:43 pm

Nutting out an intent handler:

Each external gets assigned a unique request code by the engine.

We have an OnActivityResultListener interface to handle results.

Code: Select all

	public static interface OnActivityResultListener {
		void onActivityResult(int resultCode, Intent result);
	}
We have a LC.startActivity(Intent,OnActivityResultListener) api.

On the generated code side we create a global reference from the OnActivityResultListener and call startActivity with the intent and the externals request code on the engine activity.

When the engine handles onActivityResult it maps the requestCodes to the appropriate external, then calls the onActivityResult method on the OnActivityResultListener and then releases the global reference to it.

Does that all work?
LiveCode User Group on Facebook : http://FaceBook.com/groups/LiveCodeUsers/

monte
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 1564
Joined: Fri Jan 13, 2012 1:47 am
Contact:

Re: android externals

Post by monte » Sun Jul 21, 2013 10:51 pm

Hmm... I had my head in JNI when I thought up that. The OnActivityResultListener can just be a static variable of the LC class. That way when the engine handles onActivityResult it just calls (via the externals interface) something like LC.onActivityResult which is then called on the current OnActivityResultListener. It also occurs to me that if the engines request code for the external is set as a static variable in LC then to start the activity we don't need to go via JNI.
LiveCode User Group on Facebook : http://FaceBook.com/groups/LiveCodeUsers/

monte
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 1564
Joined: Fri Jan 13, 2012 1:47 am
Contact:

Re: android externals

Post by monte » Mon Jul 22, 2013 12:40 pm

Playing with these ideas and I'm not entirely sure how to get the engine to call the external without going via a handler...
LiveCode User Group on Facebook : http://FaceBook.com/groups/LiveCodeUsers/

monte
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 1564
Joined: Fri Jan 13, 2012 1:47 am
Contact:

Re: android externals

Post by monte » Tue Jul 23, 2013 1:28 am

I think I'm leaning towards my original plan of making the com.runrev.android package available to externals (should just be adding it to the classpath) and modifying LiveCodeActivity to give each intent a unique request code and OnActivityResultListener. This would mean changes to the current intent handlers in the Engine class. Probably need some confirmation that that's going to be accepted before I start playing with it. Trying to hack ways to do this via JNI and the externals interface when the LiveCodeActivity class is just there seems silly. This model also makes it easy to add other externals interfaces to appropriate classes if we need them and given we will probably end up tying android external builds to the livecode repo anyway it seems to be a no-brainer.
LiveCode User Group on Facebook : http://FaceBook.com/groups/LiveCodeUsers/

LCMark
Livecode Staff Member
Livecode Staff Member
Posts: 1209
Joined: Thu Apr 11, 2013 11:27 am

Re: android externals

Post by LCMark » Tue Jul 23, 2013 9:31 am

@monte: It isn't wise to publically expose the LiveCodeActivity class since it is private - exposing means that it can't change as it needs to in the future and whilst we only guarantee source-compatibility for lcidl externals at the moment as the engine evolves, when the LC APIs are engine-side, this will turn into binary-compatibility. Functionality that externals (and modules) have access to has to be through very clean and specific APIs otherwise we are only making problems for ourselves later on down the line.

I'll try and find some time to ponder this implementation-wise a little later on - it would be easier to have the call on the Java side, as that solves the issue of what to do with Intent results. Essentially, we could add a call that runs the intent, waits for it to finish then returns the Intent (result) to the caller. Or, one that invokes a method of a class (i.e. standard java callback logic).

Locked

Return to “Engine Contributors”