JNI/Android: Java events calling pascal code

classic Classic list List threaded Threaded
18 messages Options
Reply | Threaded
Open this post in threaded view
|

JNI/Android: Java events calling pascal code

patspiper
Hi,

Is it possible to implement using JNI java events callbacks without
writing java code? For example, the android media player defines:

setOnCompletionListener(MediaPlayer.OnCompletionListener listener)
which registers a callback to be invoked when the end of a media source
has been reached during playback.

How can a pascal method be assigned to that callback so that it is
called when the end has been reached?

Stephano
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: JNI/Android: Java events calling pascal code

fredvs
Hello.

take a look here :
=> http://wiki.freepascal.org/Using_Pascal_Libraries_with_Java

At =>  "Dealing with callback procedures".
Many thanks ;-)
Reply | Threaded
Open this post in threaded view
|

Re: JNI/Android: Java events calling pascal code

patspiper
On 21/04/14 21:53, fredvs wrote:
> Hello.
>
> take a look here :
> => http://wiki.freepascal.org/Using_Pascal_Libraries_with_Java
>
> At =>  "Dealing with callback procedures".

The wiki page describes how to interact bi-directionally between your
own java and pascal code. My question is whether it is possible to hook
into (as an example) the java media player events without writing java
code. As for the opposite direction, calling the media player's Start
method from pascal does not need any java code.

So the question remains.

Stephano
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: JNI/Android: Java events calling pascal code

leledumbo
Administrator
> My question is whether it is possible to hook
into (as an example) the java media player events without writing java
code. As for the opposite direction, calling the media player's Start
method from pascal does not need any java code.

If it can be done from C, then it can be done from Pascal as well. In fact, the Java compiler frontend is written in C, which initializes JVM and then call the Java compiler (which is written in Java). The problem now is that you will have to initialize JVM yourself (which I don't have experience in) and interact with the existing Java code from Pascal through JNI.
Reply | Threaded
Open this post in threaded view
|

Re: JNI/Android: Java events calling pascal code

patspiper
On 22/04/14 12:02, leledumbo wrote:

>> My question is whether it is possible to hook
> into (as an example) the java media player events without writing java
> code. As for the opposite direction, calling the media player's Start
> method from pascal does not need any java code.
>
> If it can be done from C, then it can be done from Pascal as well. In fact,
> the Java compiler frontend is written in C, which initializes JVM and then
> call the Java compiler (which is written in Java). The problem now is that
> you will have to initialize JVM yourself (which I don't have experience in)
> and interact with the existing Java code from Pascal through JNI.

I can already launch the android media player from pascal using JNI
(without any java code), and I don't think there is a problem handling
the player's events IF a java wrapper class that intercepts the player's
events and calls native (pascal) methods is implemented.

My question is if it can be done without a java wrapper class as this
would make android programming much easier (unless I have misunderstood
your reply).

Stephano
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: JNI/Android: Java events calling pascal code

leledumbo
Administrator
> My question is if it can be done without a java wrapper class as this
would make android programming much easier (unless I have misunderstood
your reply).

Perhaps I misunderstood your question in the first place. Could you instead draw a diagram (flowchart?) and emphasize (red circle or something) the part you wish to create?
Reply | Threaded
Open this post in threaded view
|

Re: JNI/Android: Java events calling pascal code

patspiper
On 22/04/14 18:36, leledumbo wrote:
>> My question is if it can be done without a java wrapper class as this
> would make android programming much easier (unless I have misunderstood
> your reply).
>
> Perhaps I misunderstood your question in the first place. Could you instead
> draw a diagram (flowchart?) and emphasize (red circle or something) the part
> you wish to create?

Let's consider a Lazarus TTimer. You set its interval, assign a method
for the OnTimer event, and set enabled to True. Once the interval is
over, OnTimer will fire and call the assigned method. Note that we did
not touch the TTimer component's code.

Now to the java media player: You assign a pascal method to the
OnCompetion event (the question is how), and start the player
(pascal/jni). Once the song is over, OnCompletion will fire and call the
assigned pascal method.

Pascal/JNI pseudo code:

procedure Play;
begin
   jmediaplayer.Oncompletion := @MyOnCompletion; // how?
   jmediaplayer.start;  // the actual code needs to get the jclass,
jmethodID and make the start call (no java code involved)
end;

procedure MyOnCompletion(AEnv: Penv; aObj: jObject)
begin
  ShowMessage('Song has ended');
end;

I hope this is clearer.

Stephano
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: JNI/Android: Java events calling pascal code

leledumbo
Administrator
> Now to the java media player: You assign a pascal method to the
OnCompetion event (the question is how), and start the player
(pascal/jni). Once the song is over, OnCompletion will fire and call the
assigned pascal method.

Ah... I see. That is AFAIK not possible. Java doesn't have the procedural type concept as it has much more OOP forced. Common Java code for callback is to pass an anonymous inner class implementing expected interface. The problem is that AFAIK JNI doesn't have access to dynamic class creation like that, you will need to write a Java wrapper which implements the interface and assign the Pascal callback.
Reply | Threaded
Open this post in threaded view
|

Re: JNI/Android: Java events calling pascal code

patspiper
On 22/04/14 19:26, leledumbo wrote:

>> Now to the java media player: You assign a pascal method to the
> OnCompetion event (the question is how), and start the player
> (pascal/jni). Once the song is over, OnCompletion will fire and call the
> assigned pascal method.
>
> Ah... I see. That is AFAIK not possible. Java doesn't have the procedural
> type concept as it has much more OOP forced. Common Java code for callback
> is to pass an anonymous inner class implementing expected interface. The
> problem is that AFAIK JNI doesn't have access to dynamic class creation like
> that, you will need to write a Java wrapper which implements the interface
> and assign the Pascal callback.

So there is no way out without java coding. Moreover, each jclass that
has 'events' will need a wrapper class.

However, it seems there might be a better solution which uses a fixed
java snippet for all classes (using a dynamic proxy). As I am not very
involved with java, pls have a look at:
https://groups.google.com/forum/#!topic/android-ndk/SRgy93Un8vM
especially the post before the last. Maybe you can shed more light on this?

Thanks,
Stephano
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: JNI/Android: Java events calling pascal code

leledumbo
Administrator
> However, it seems there might be a better solution which uses a fixed
java snippet for all classes (using a dynamic proxy). As I am not very
involved with java, pls have a look at:
https://groups.google.com/forum/#!topic/android-ndk/SRgy93Un8vM
especially the post before the last. Maybe you can shed more light on this?

Hmm...that's beyond my Java skill. Since Felipe who started the topic, you can try PM him instead.
Reply | Threaded
Open this post in threaded view
|

Re: JNI/Android: Java events calling pascal code

Felipe Monteiro de Carvalho
On Wed, Apr 23, 2014 at 6:10 AM, leledumbo <[hidden email]> wrote:
> Hmm...that's beyond my Java skill. Since Felipe who started the topic, you
> can try PM him instead.

So looking at what he originally posted:

setOnCompletionListener(MediaPlayer.OnCompletionListener listener)

And looking into the documentation:

http://developer.android.com/reference/android/media/MediaPlayer.OnCompletionListener.html

you need to provide a class which implements the
MediaPlayer.OnCompletionListener interface:

There is nothing in JNI unfortunately which would allow us to create
new classes. JNI is very limited, unlike objc runtime which gives us
access to everything, JNI gives us a limited access to the Java world.

I already asked in the past in Java/Android groups about this, how to
get rid of Java when you need to pass a class which implements and
interface.

The answer is that it is possible: You need to create the class in
...... java bytecode =D And then pass it to Java.

At this point I gave up, considering it too awkward and wrote my
software part in Java and part in Pascal.

Ideally it would not be so hard if we had a bytecode generator which
accepts as input things like classname, which interfaces it will
implement, list of functions and address to their implementation, etc,
etc. But we don't have at the moment AFAIK.

So maybe someone braver will actually do this, since it is possible =D
But I didn't for my Android app in the app store (True Democracy)....

--
Felipe Monteiro de Carvalho
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: JNI/Android: Java events calling pascal code

Chriss Kalogeropoulos
Hello everyone,

a couple years ago i tried the same thing. The task was to implement a JavaPOS driver handler from Delphi/FPC code. 
The actual driver was implemented in C++ and it used a Java interface. My code was the glue between the application (Delphi/FPC) and the driver, it had to hook the events and call the appropriate methods for printing etc (it was a POS printer driver).

I found that the only way to hook a native implemented listener to the java class was either to write a small piece of code in java to do the dispatching to my code OR use dynamic compilation to create the Java byte code. Basically i had to write the java code inside my dll (in a constact string) and pass this to the Java compiler to create the byte code in memory.
This needed a lot of work and i dropped it since the actual java code was less than 30 lines and it was very generic, so it was not worth the effort. 
Check this 

This needs Java 6 (which was not an option in my case, i had to use older versions). It might help you.
Also it needs to store the source files locally otherwise more dynamic class generation will be needed.
The link above has the info you need.

Chriss



On Wed, Apr 23, 2014 at 12:31 PM, Felipe Monteiro de Carvalho <[hidden email]> wrote:
On Wed, Apr 23, 2014 at 6:10 AM, leledumbo <[hidden email]> wrote:
> Hmm...that's beyond my Java skill. Since Felipe who started the topic, you
> can try PM him instead.

So looking at what he originally posted:

setOnCompletionListener(MediaPlayer.OnCompletionListener listener)

And looking into the documentation:

http://developer.android.com/reference/android/media/MediaPlayer.OnCompletionListener.html

you need to provide a class which implements the
MediaPlayer.OnCompletionListener interface:

There is nothing in JNI unfortunately which would allow us to create
new classes. JNI is very limited, unlike objc runtime which gives us
access to everything, JNI gives us a limited access to the Java world.

I already asked in the past in Java/Android groups about this, how to
get rid of Java when you need to pass a class which implements and
interface.

The answer is that it is possible: You need to create the class in
...... java bytecode =D And then pass it to Java.

At this point I gave up, considering it too awkward and wrote my
software part in Java and part in Pascal.

Ideally it would not be so hard if we had a bytecode generator which
accepts as input things like classname, which interfaces it will
implement, list of functions and address to their implementation, etc,
etc. But we don't have at the moment AFAIK.

So maybe someone braver will actually do this, since it is possible =D
But I didn't for my Android app in the app store (True Democracy)....

--
Felipe Monteiro de Carvalho
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: JNI/Android: Java events calling pascal code

patspiper
In reply to this post by Felipe Monteiro de Carvalho
On 23/04/14 12:31, Felipe Monteiro de Carvalho wrote:
On Wed, Apr 23, 2014 at 6:10 AM, leledumbo [hidden email] wrote:
Hmm...that's beyond my Java skill. Since Felipe who started the topic, you
can try PM him instead.
So looking at what he originally posted:

setOnCompletionListener(MediaPlayer.OnCompletionListener listener)

And looking into the documentation:

http://developer.android.com/reference/android/media/MediaPlayer.OnCompletionListener.html

you need to provide a class which implements the
MediaPlayer.OnCompletionListener interface:

There is nothing in JNI unfortunately which would allow us to create
new classes. JNI is very limited, unlike objc runtime which gives us
access to everything, JNI gives us a limited access to the Java world.

I already asked in the past in Java/Android groups about this, how to
get rid of Java when you need to pass a class which implements and
interface.

The answer is that it is possible: You need to create the class in
...... java bytecode =D And then pass it to Java.

At this point I gave up, considering it too awkward and wrote my
software part in Java and part in Pascal.

Ideally it would not be so hard if we had a bytecode generator which
accepts as input things like classname, which interfaces it will
implement, list of functions and address to their implementation, etc,
etc. But we don't have at the moment AFAIK.

So maybe someone braver will actually do this, since it is possible =D
But I didn't for my Android app in the app store (True Democracy)....

Now that I have re-read the (your) thread I had pointed out in my post, and went through a lot of googling, I think it is possible to create one static bit of java code (dynamic proxy) and instantiate that class from pascal/jni:

The java code:

public class NativeInvocationHandler implements InvocationHandler {
public NativeInvocationHandler(long ptr) {
this.ptr = ptr;
}
public static Object newInstance(Class clazz, long ptr) {
return java.lang.reflect.Proxy.newProxyInstance(
clazz.getClassLoader(),
clazz.getInterfaces(),
new
NativeInvocationHandler(ptr));
}

Object invoke(Object proxy, Method method, Object[] args) {
return invoke0(proxy, method, args);
}
native private Object invoke0(Object proxy, Method method, Object[] args);
private long ptr;
}

Pascal:
function invoke0(env: PEnv; thiz: jobject; method: jmethod; args: jobjectArray): jobject;
var
  ptrField: jFieldID;
  jptr: jlong;
  lMediaPlayerEvent: TMediaPlayerEvent
begin
  ptrField := GetFieldID(GetObjectClass(thiz), 'ptr', 'J');
  jptr := GetLongField(thiz, ptrField);
  lMediaPlayerEvent := TMediaPlayerEvent(jptr);
  result := lMediaPlayerEvent.invoke(env, method, args);
end;

TMediaPlayerEvent = class(TObject)
public
  function invoke(env: PEnv; method: jmethod; args: jobjectArray): jobject;
end;

TMediaPlayerEvent.function invoke(env: PEnv; method: jmethod; args: jobjectArray): jobject;
begin
  // code to handle events
end;

Then:
- gMediaPlayerEvent := TMediaPlayerEvent.create;
- create the java media player
- call static method NativeInvocationHandler.newInstance(javamediaplayerclass, gMediaPlayerEvent)
- set the java media player's setOnCompletionListener(result of
NativeInvocationHandler.newInstance)

Now java media player events will be channelled to gMediaPlayerEvent.invoke

The code above is untested and written hastily for the purpose of this email. I plan to test it today if I have enough time.
Comments/corrections are welcome.

Stephano


_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: JNI/Android: Java events calling pascal code

patspiper
In reply to this post by Chriss Kalogeropoulos
On 23/04/14 13:20, Chriss Kalogeropoulos wrote:

> Hello everyone,
>
> a couple years ago i tried the same thing. The task was to implement a
> JavaPOS driver handler from Delphi/FPC code.
> The actual driver was implemented in C++ and it used a Java interface.
> My code was the glue between the application (Delphi/FPC) and the
> driver, it had to hook the events and call the appropriate methods for
> printing etc (it was a POS printer driver).
>
> I found that the only way to hook a native implemented listener to the
> java class was either to write a small piece of code in java to do the
> dispatching to my code OR use dynamic compilation to create the Java
> byte code. Basically i had to write the java code inside my dll (in a
> constact string) and pass this to the Java compiler to create the byte
> code in memory.
> This needed a lot of work and i dropped it since the actual java code
> was less than 30 lines and it was very generic, so it was not worth
> the effort.
> Check this
> http://www.javablogging.com/dynamic-in-memory-compilation/
>
> This needs Java 6 (which was not an option in my case, i had to use
> older versions). It might help you.
> Also it needs to store the source files locally otherwise more dynamic
> class generation will be needed.
> The link above has the info you need.

If the java code is static, why would one need dynamic compilation?

Stephano
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: JNI/Android: Java events calling pascal code

fredvs
In reply to this post by patspiper
Hello.

Hum, if you are not obliged to use Java media-player, you may use
=> https://github.com/fredvs/uoslib.

That fpc audio library is Java-comatible and can do easy callbacks...
Many thanks ;-)
Reply | Threaded
Open this post in threaded view
|

Re: JNI/Android: Java events calling pascal code

Chriss Kalogeropoulos
In reply to this post by patspiper

The main reason is to avoid distributing extra files with the application. Having just one exe or dll that can handle the "details" is much better.

I was also hoping to reuse the code in other similar projects that had different listeners. For example, a barcode reader javapos driver has different event signatures (different listener class), so it needs different java code. It would be nice if it could be encapsulated inside the pascal class instead of an external file.

Anyway the task is doable if someone can write the java code in a temporary file and invoke the compiler. If this is not possible I do not know if it can be done.

If you do not care about that then just use java glue code, it's simpler.

Στις 23 Απρ 2014 2:34 μ.μ., ο χρήστης "patspiper" <[hidden email]> έγραψε:
On 23/04/14 13:20, Chriss Kalogeropoulos wrote:
Hello everyone,

a couple years ago i tried the same thing. The task was to implement a JavaPOS driver handler from Delphi/FPC code.
The actual driver was implemented in C++ and it used a Java interface. My code was the glue between the application (Delphi/FPC) and the driver, it had to hook the events and call the appropriate methods for printing etc (it was a POS printer driver).

I found that the only way to hook a native implemented listener to the java class was either to write a small piece of code in java to do the dispatching to my code OR use dynamic compilation to create the Java byte code. Basically i had to write the java code inside my dll (in a constact string) and pass this to the Java compiler to create the byte code in memory.
This needed a lot of work and i dropped it since the actual java code was less than 30 lines and it was very generic, so it was not worth the effort.
Check this
http://www.javablogging.com/dynamic-in-memory-compilation/

This needs Java 6 (which was not an option in my case, i had to use older versions). It might help you.
Also it needs to store the source files locally otherwise more dynamic class generation will be needed.
The link above has the info you need.

If the java code is static, why would one need dynamic compilation?

Stephano

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: JNI/Android: Java events calling pascal code

patspiper
On 23/04/14 23:40, Chriss Kalogeropoulos wrote:

>
> The main reason is to avoid distributing extra files with the
> application. Having just one exe or dll that can handle the "details"
> is much better.
>
> I was also hoping to reuse the code in other similar projects that had
> different listeners. For example, a barcode reader javapos driver has
> different event signatures (different listener class), so it needs
> different java code. It would be nice if it could be encapsulated
> inside the pascal class instead of an external file.
>
> Anyway the task is doable if someone can write the java code in a
> temporary file and invoke the compiler. If this is not possible I do
> not know if it can be done.
>
> If you do not care about that then just use java glue code, it's simpler.
>

The preliminary good news: I am able to use java events without java
coding (other than one fixed java bit). I have tested the java media
player and once the song is over, the pascal event is fired successfully :)

The fixed bit of java code can handle any event with any signature from
any object. I have some minor but time consuming hurdles/bugs to
overcome, but once done, only pascal coding will be needed for any java
class.

Stephano
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: JNI/Android: Java events calling pascal code

tylercaro
In reply to this post by Chriss Kalogeropoulos
Chriss Kalogeropoulos wrote
he main reason is to avoid distributing extra files with the application. Having just one exe or dll that can handle the "details" is much better.

I was also hoping to reuse the code in other similar projects that had different listeners. For example, a barcode reader javapos driver has different event signatures (different listener class), so it needs different java code. It would be nice if it could be encapsulated inside the pascal class instead of an external file.
that's good point, we can find other barcode recognition algorithm java from this website. just wondering can it be used at this place. or we can modify it.