Lazarus

Programming => Operating Systems => Android => Topic started by: LA.Center on February 04, 2012, 12:28:31 am

Title: Android API
Post by: LA.Center on February 04, 2012, 12:28:31 am
Is there any Android API pascal translation for camera, phone book, etc ... using Android Native SDK?
Title: Re: Android API
Post by: Leledumbo on February 04, 2012, 04:55:38 am
The FPC JVM backend port with Android target has them.
Title: Re: Android API
Post by: felipemdc on February 04, 2012, 07:58:42 am
Is there any Android API pascal translation for camera, phone book, etc ... using Android Native SDK?

To start with: How are you writing your application? Is it a Pascal shared object?

"Android Native SDK" is a confusing term. Android has 2 sets of APIs: NDK and SDK

Supposing you are talking about the NDK, all translations I have so far are here:

http://svn.freepascal.org/cgi-bin/viewvc.cgi/trunk/lcl/interfaces/customdrawn/android/?root=lazarus

But that does not include camera nor phone book.  I think that camera only came in a very recent NDK, if at all, and likely phone book is not in the NDK at all. I am targeting Android 2.2+ so I don't have the latest NDK APIs, but I am not sure if those are really that useful anyway.

For SDK APIs, which are the vast majority in Android, you can access all of them either directly from JNI, which works very nicely for simple method calls, but often Android APIs require some wierd syntax, creating classes on the fly and adding methods to handle things on the fly, implementing interfaces, etc ... so if you are facing problematic syntax then you can create a Java method which does the service and you call it via JNI, like this:

http://svn.freepascal.org/cgi-bin/viewvc.cgi/trunk/lcl/interfaces/customdrawn/customdrawnwslazdeviceapis.pas?view=markup&root=lazarus

http://svn.freepascal.org/cgi-bin/viewvc.cgi/trunk/examples/androidlcl/android/src/com/pascal/lcltest/LCLActivity.java?view=markup&root=lazarus

In some places I could have done the direct JNI method, but when I wrote those I didn't jet know how how to call methods in parameters in JNI, but now I already mastered that, so in the future the LCL will likely see more direct calls.
Title: Re: Android API
Post by: LA.Center on February 04, 2012, 12:37:50 pm
@felipemdc as I always say, you the man.

another question, I am using LCL Android but I can make the form black, how can I make the from background black?

---

found it, you can change it in common_draw
Title: Re: Android API
Post by: LA.Center on February 04, 2012, 06:48:59 pm
pascal side I have

Code: [Select]

procedure TCDWidgetSet.LazDeviceAPIs_OpenUrl(url: string);
var
  lJavaString: jstring;
  lStr: String;
begin
  lStr := url;
  lJavaString :=javaEnvRef^^.NewStringUTF(javaEnvRef, PChar(lStr));
  javaEnvRef^^.SetObjectField(javaEnvRef, javaActivityObject, JavaField_lcltext, lJavaString);
  javaEnvRef^^.CallVoidMethod(javaEnvRef, javaActivityObject, javaMethod_LCLDoOpenUrl);
end;

and on the java side I have

Code: [Select]
public void LCLDoOpenUrl(String url)
{
  Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
  startActivity(browserIntent);
}

when I make the call, the app exits without any warning, what am I doing wrong here?

---

Solved, had forgotten to assign and initialize the Java Method
Title: Re: Android API
Post by: felipemdc on February 05, 2012, 04:40:27 pm
Hello,

Maybe if you implementing those things you could send over patches and get merged into the official trunk? =)

But first update your subversion, it looks like you got inspired by an older svn revision but now the design is a bit different. I added a new class to centralize those misc device calls called TCDLazDeviceAPI in unit customdrawnwslazdeviceapis.pas instead of putting in LCLIntf as before. LCLIntf is getting too messy.

PS: Also the code showed a bug. It puts the string into a field but the java side expects it in a parameter. You have to use CallVoidMethodA instead of CallVoidMethod to pass parameters. Search for it in lcl/interfaces/customdrawn there are some places where I used CallVoidMethodA
Title: Re: Android API
Post by: LA.Center on February 08, 2012, 04:22:00 pm
I will submit some API code as soon I figure out how to retrieve and read a String Field from java to pascal.

do you know how?

for example I have a String Field lTXTCallerID and it calls a native void method. now on the native side I need to get the Field lTXTCallerID and convet it to pascal string.

This is the only thing I am stuck, when I figure that out, I will create a complete API for camera, contacts, etc... and send it to you so you can integrate it.
Title: Re: Android API
Post by: felipemdc on February 08, 2012, 04:36:53 pm
for example I have a String Field lTXTCallerID and it calls a native void method. now on the native side I need to get the Field lTXTCallerID and convet it to pascal string.

Use GetObjectField to the the field, since jstring is an object and use GetStringUTFChars to get a UTF-8 PChar:

      GetObjectField:function(Env:PJNIEnv;Obj:JObject;FieldID:JFieldID):JObject;{$ifdef mswindows}stdcall;{$else}cdecl;{$endif}
      GetStringUTFChars:function(Env:PJNIEnv;Str:JString;var IsCopy:JBoolean):pchar;{$ifdef mswindows}stdcall;{$else}cdecl;{$endif}
      ReleaseStringUTFChars:procedure(Env:PJNIEnv;Str:JString;const Chars:pchar);{$ifdef mswindows}stdcall;{$else}cdecl;{$endif}

I used it at some point in LCL-CustomDrawn but now it isn't used anymore... and I don't know in which revision it was nor in which file... but I used that and it worked.

Quote
This is the only thing I am stuck, when I figure that out, I will create a complete API for camera, contacts, etc... and send it to you so you can integrate it.

It would be good to see some partial code to know if you are writing it in a good way. A way which can be integrated immediately without changes ... otherwise we will have a problem later on to change everything to the expected architecture. I prefer implementing all such APIs in the unit customdrawnwslazdeviceapis.pas And make objects in the unit lazdeviceapis which expose the functionality via the LCL. As opposed to LCLIntf functions.
Title: Re: Android API
Post by: LA.Center on February 08, 2012, 06:29:19 pm
GetStringUTFChars is actually the point where I am stuck

this dose not work?

Code: [Select]
procedure Java_AFX_Trigger(); cdecl;
var
  eo: jobject;
  eb: jboolean;
  e: string;
  str: TStringList;
begin
  eb := 1;
  eo := javaEnvRef^^.GetObjectField(javaEnvRef, eo, java_EventVar);
  e := javaEnvRef^^.GetStringUTFChars(javaEnvRef, eo, eb); //<- HERE IT BREAKS
  if e = 'TEST' then
  begin
    Log('TEST IT WORKS MAN :) <br>');
  end;
end;

ans sure I will do the changes in those units :)
Title: Re: Android API
Post by: felipemdc on February 08, 2012, 06:48:10 pm
This code gets the field registered as java_EventVar from object eo, which is an uninitialized variable:

  eo := javaEnvRef^^.GetObjectField(javaEnvRef, eo, java_EventVar);
Title: Re: Android API
Post by: LA.Center on February 08, 2012, 07:04:23 pm
I have it initialized, and added it to the Java Side. This is just a test, I am doing all my test in a different project :)

So it is initialized, and on the Java Side I assign 'TEST' and make a api call to Call_AFX_Trigger;

very simple, I need to be able to read strings otherwise most of the API can not be used because filenames and servicenames need to set and java part should trigger tell the LCL to retrieve the value to complete the event.

all tests are OK except for reading a string part, and I have not found a other method, except maybe writing to file and reading from file but that would be just stupid.
Title: Re: Android API
Post by: felipemdc on February 08, 2012, 07:43:01 pm
I will take a look tomorrow.
Title: Re: Android API
Post by: felipemdc on February 10, 2012, 02:19:28 pm
I had to change the jni.pas header and passed nil for isCopy. I don't know if this was your problem. Check these revisions which added code which read strings from Java and create new strings:

http://svn.freepascal.org/cgi-bin/viewvc.cgi?view=rev&root=lazarus&revision=35291

http://svn.freepascal.org/cgi-bin/viewvc.cgi?view=rev&root=lazarus&revision=35293

And this file in general:

http://svn.freepascal.org/cgi-bin/viewvc.cgi/trunk/lcl/interfaces/customdrawn/customdrawnwslazdeviceapis.pas?view=markup&root=lazarus&pathrev=35293

Also note there how I managed to do everything in Pascal, without Java. I think it might be a better way for simple stuff like just getting a service and calling a method from it, checkout the Vibrate method that I wrote. And leave Java for more complex syntax like building interfaces, overriding methods, etc.
Title: Re: Android API
Post by: LA.Center on February 14, 2012, 06:25:57 pm
yes that worked :) thx, now I have a other mind bugle. I created a very simple app with custom draw, set all permissions. Samsung Galaxy works just fine but on a phone it crashes (very fast), do you have any idea why. its not even logging something.

I am suspecting that the so file is not accepted, shouldn't the generated so be transparent?
Title: Re: Android API
Post by: felipemdc on February 15, 2012, 07:24:47 am
Samsung Galaxy works just fine but on a phone it crashes (very fast), do you have any idea why. its not even logging something.

Could you rephrase that? I cannot understand this sentense. You are saying that it doesn't work on Samsung Galaxy or that it works there and not in another phone? And please be more specific about the model, I know "Samsung Galaxy S", Samsung Galaxy Y", "Samsung Galaxy 5", "Samsung Galaxy Pro", etc, etc, which are all very different phones. There is no such thing as only "Samsung Galaxy" without a 3rd identifier.

How are you installing the APK? Installing the APK goes fine?

Here I tested on a lot of phones and all worked: HTC Wildfire, Sony Erricson Xperia Mini, Nexus One, Alcatel
Title: Re: Android API
Post by: LA.Center on February 18, 2012, 12:59:40 pm
sorry, I meant Samsung Galaxy G1010 Wifi, there it works, but on some not for example, and I found out that even though I specified STORAGE permissions some Androids stay read-only, therefor the crash.

Anyhow, I have also tried a slight different approach, and the result is attached here http://forums.gridplusplus.com/index.php?topic=677.msg917#new (sorry for directing to a other site but here you can not attach larger than 250 KB).

and it was better for us to create a native proxy interface to Android SDK, instead of customdraw, don't get me wrong I still think CustomDraw is the way to go for Lazarus because of LCL compatibility but we thought it became really slow once you had a lot of components on screen, we also kind of had to go with the native proxy interface because we have also 3FX (GLES) components that need to be rendered.

I think you the rock n roller here, getting Android up and running ;) and I personally have learned a lot from you/your code. Thank you man!
Title: Re: Android API
Post by: felipemdc on February 18, 2012, 01:39:46 pm
and it was better for us to create a native proxy interface to Android SDK, instead of customdraw, don't get me wrong I still think CustomDraw is the way to go for Lazarus because of LCL compatibility but we thought it became really slow once you had a lot of components on screen,

Yes, it stills needs a lot of work on optimizing for speed. Currently it is optimized for using the smallest amount of RAM possible, but one could reuse already drawn elements and make it much faster. Also the text should be faster via LazFreeType then via the native Android text rendering. Also there is no support yet for partial invalidation. For scrolling one could draw and store the entire form area instead of only the visible part(which requires more RAM), and so on. LCL-CustomDrawn is a young interface, needs time (and patches) to mature and be more optimized.
Title: Re: Android API
Post by: felipemdc on March 19, 2012, 11:37:08 am
You shouldnt have given up so early, now I have implemented the painting optimization and it is fast even with many controls in the form.