Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2014-04

JNI/Android: Java events calling pascal code

18 messages · 6 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

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

Reply by email

patspiper
to fredvs
fredvs wrote 6 lines
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

Reply by email

leledumbo
to patspiper
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.

View this message in context: http://free-pascal-general.1045716.n5.nabble.com/JNI-Android-Java-events-calling-pascal-code-tp5718988p5718991.html Sent from the Free Pascal - General mailing list .

Reply by email

patspiper
to leledumbo
leledumbo wrote 10 lines
> 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

Reply by email

leledumbo
to patspiper
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?

View this message in context: http://free-pascal-general.1045716.n5.nabble.com/JNI-Android-Java-events-calling-pascal-code-tp5718988p5718993.html Sent from the Free Pascal - General mailing list .

Reply by email

patspiper
to leledumbo
leledumbo wrote 7 lines
> 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

Reply by email

leledumbo
to patspiper
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.

View this message in context: http://free-pascal-general.1045716.n5.nabble.com/JNI-Android-Java-events-calling-pascal-code-tp5718988p5718995.html Sent from the Free Pascal - General mailing list .

Reply by email

patspiper
to leledumbo
leledumbo wrote 11 lines
> 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

Reply by email

leledumbo
to patspiper
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.

View this message in context: http://free-pascal-general.1045716.n5.nabble.com/JNI-Android-Java-events-calling-pascal-code-tp5718988p5718997.html Sent from the Free Pascal - General mailing list .

Reply by email

Felipe Monteiro de Carvalho
to leledumbo
leledumbo 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

Reply by email

Chriss Kalogeropoulos
to Felipe Monteiro de Carvalho

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.

Chriss

On Wed, Apr 23, 2014 at 12:31 PM, Felipe Monteiro de Carvalho <

Show quoted text 48 lines
wrote: On Wed, Apr 23, 2014 at 6:10 AM, leledumbo 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 - http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal

Reply by email

patspiper
to Felipe Monteiro de Carvalho: So looking at what he originally posted: setOnCompletionListener(MediaPlayer.OnCompletionL…
Felipe Monteiro de Carvalho wrote 35 lines
On Wed, Apr 23, 2014 at 6:10 AM, leledumbo 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

Reply by email

patspiper
to Chriss Kalogeropoulos: a couple years ago i tried the same thing. The task was to implement a JavaPOS driver…
Chriss Kalogeropoulos wrote 26 lines
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

Reply by email

fredvs
to patspiper: Is it possible to implement using JNI java events callbacks without writing java code?…

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 ;-)

View this message in context: http://free-pascal-general.1045716.n5.nabble.com/JNI-Android-Java-events-calling-pascal-code-tp5718988p5719002.html Sent from the Free Pascal - General mailing list .

Reply by email

Chriss Kalogeropoulos

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" έγραψε:

Chriss Kalogeropoulos wrote 26 lines
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

Reply by email

patspiper
to Chriss Kalogeropoulos
Chriss Kalogeropoulos wrote 17 lines
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

Reply by email

tylercaro
to Chriss Kalogeropoulos: The main reason is to avoid distributing extra files with the application. Having just…

Chriss Kalogeropoulos wrote

Show quoted text 8 lines
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 <http://www.keepdynamic.com/java-barcode-reader/> from this website. just wondering can it be used at this place. or we can modify it.

View this message in context: http://free-pascal-general.1045716.n5.nabble.com/JNI-Android-Java-events-calling-pascal-code-tp5718988p5719582.html Sent from the Free Pascal - General mailing list .

Reply by email