Sign in Join
Wiki copytemporary

Android Programming: what changed

Revision 0 to 1. Removed lines have a minus sign; added lines have a plus sign.

Title: Android Programming

OldNewLine
1+*(Android only)*
2+
3+See also [[Custom Drawn Interface/Android]]
4+
5+Knowing general Android programming can be very useful to help develop the Lazarus Android Interface.
6+
7+## Platform Tips
8+
9+## How to...
10+
11+### Build the NDK OpenGL example
12+
13+Just follow these steps:
14+
15+**Step 1** - Download and install the Android NDK, Android SDK and Ant. More information here: [[Android Interface/Using the Android SDK, Emulator and Phones|Android_Interface/Using_the_Android_SDK%2C_Emulator_and_Phones]]
16+
17+**Step 2** - Install the pre-compiled FPC cross-compiler. Instructions here: [[Android Interface|Android_Interface#Using_the_pre-compiled_compiler]]
18+
19+**Step 3** - Download the latest lazarus-ccr sourceforge code:
20+
21+``` bash
22+svn co https://lazarus-ccr.svn.sourceforge.net/svnroot/lazarus-ccr lazarus-ccr
23+```
24+
25+or if you think it is too big you can download just the folder lazarus-ccr/bindings/android-ndk
26+
27+**Step 4** - Building the Pascal Library
28+
29+> **Note:** In the steps below, the directory /home/felipe/Programas or ~/Programas is used. Please adjust if your paths are different.
30+
31+Open the project lazarus-ccr/bindings/android-ndk/examples/opengltest/opengltest.lpi
32+
33+Go to Project-\>Project Options-\>Paths and where is written "Libraries -Fl" you should see a value like this:
34+
35+`/home/felipe/Programas/android-ndk-r5/platforms/android-9/arch-arm/usr/lib`
36+
37+Change it to the correct path in your system which points to the NDK and to the library folder for your minimal required Android API Level
38+
39+Now build the project using Lazarus.
40+
41+**Step 5** - Configuring the build environment
42+
43+Open the file opengltest/local.properties. Change this line to point to your SDK location:
44+
45+`sdk.dir=/home/felipe/Programas/android-sdk-linux`
46+
47+**Step 6** - Buildings the APK
48+
49+Open a terminal and type these commands:
50+
51+``` bash
52+cd lazarus-ccr/bindings/ndk/examples/opengltest/android
53+ant debug
54+```
55+
56+The APK file will be placed in opengltest/android/bin/
57+
58+**Step 7** - Install the APK
59+
60+In this step, if you get error messages about permissions read: [[Android Interface/Using the Android SDK, Emulator and Phones|Android_Interface/Using_the_Android_SDK%2C_Emulator_and_Phones#Recognition_of_devices_under_Linux]]
61+
62+The command to install our APK in the phone is:
63+
64+``` bash
65+cd opengltest/android
66+~/Programas/android-sdk-linux/platform-tools/adb install bin/OpenGLNDKTest-debug.apk
67+```
68+
69+You should see something like:
70+
71+`2395 KB/s (107299 bytes in 0.043s)`\
72+`       pkg: /data/local/tmp/OpenGLNDKTest-debug.apk`\
73+`Success`
74+
75+If you get an error message that it is already installed you can install with this command:
76+
77+``` bash
78+~/Programas/android-sdk-linux/platform-tools/adb uninstall com.pascal.opengltest
79+```
80+
81+And then you can run adb logcat to see what the log says while you start it in the phone via its newly added icon:
82+
83+``` bash
84+~/Programas/android-sdk-linux/platform-tools/adb logcat
85+```
86+
87+### Read the screen metrics
88+
89+First fill a TDisplayMetrics with the correct info:
90+
91+``` pascal
92+uses androidutil;
93+
94+var
95+ MyDisplayMetrics: TDisplayMetrics;
96+ Str: string;
97+ //
98+ lHeight, lWidth: Integer;
99+ xdpi, ydpi, lScreenSize: Single;
100+begin
101+ // ..
102+ // Objects
103+
104+ MyDisplayMetrics := TDisplayMetrics.Create;
105+ Activity.getWindowManager().getDefaultDisplay().getMetrics(MyDisplayMetrics);
106+```
107+
108+And then you can read it from the TDisplayMetrics:
109+
110+``` pascal
111+ lHeight := MyDisplayMetrics.heightPixels();
112+ lWidth := MyDisplayMetrics.widthPixels();
113+ xdpi := MyDisplayMetrics.xdpi();
114+ ydpi := MyDisplayMetrics.ydpi();
115+ lScreenSize := sqrt(sqr(lHeight / ydpi) + sqr(lWidth / xdpi));
116+ ldensity := MyDisplayMetrics.density();
117+ ldensityDpi := MyDisplayMetrics.densityDpi();
118+ scaledDensity := MyDisplayMetrics.scaledDensity();
119+```
120+
121+Note that lots of devices lie about the xdpi and ydpi, so don't trust the lScreenSize calculated above. Smartphones might report even 10 inches of screen size, while the correct is around 4.
122+
123+## Details about Android devices
124+
125+Since there are so many Android devices, it can be useful to keep track of some information about them. See also in the wikipedia Comparison of Android Devices [1](http://en.wikipedia.org/wiki/Comparison_of_Android_devices) and details about the processors in [2](https://wiki.mozilla.org/Mobile/Platforms/Android#System_Requirements).
126+
127+### Smartphones
128+
129+| Manufacturer | Model | Android API Name (Build.Model) | Processor | Android version | Multi-touch | Comments |
130+|----|----|----|----|----|----|----|
131+| HTC | Wildfire | HTC Wildfire | armv6 | 2.1=\>2.2 | Yes\|\|- | |
132+| Sony Erricson | Xperia X10 | X10i | armv7 | 1.6=\>2.1 | No\|\|- | |
133+
134+### Tablets
135+
136+| Manufacturer | Model | Android API Name (Build.Model) | Processor | Android version | Multi-touch | Comments |
137+|----|----|----|----|----|----|----|
138+| Toshiba | Folio 100 Tablet | TOSHIBA_FOLIO_AND_A | armv7 | 2.2 | Yes\|\|- | |
139+
140+### List of devices ordered by processor compatibility (ARMv6 vs ARMv7)
141+
142+<table>
143+<caption>List of ARMv7 devices</caption>
144+<tbody>
145+<tr>
146+<td>Advent Vega (P10AN01)</td>
147+<td>Dell Streak, Streak 7</td>
148+<td>HTC Desire</td>
149+<td>HTC Desire Z (T-Mobile G2)</td>
150+<td>HTC Desire HD</td>
151+</tr>
152+<tr>
153+<td>HTC Droid Incredible</td>
154+<td>HTC EVO 4G, EVO Shift 4G</td>
155+<td>HTC Glacier (T-Mobile myTouch 4G)</td>
156+<td>HTC Inspire 4G</td>
157+<td>HTC Nexus One</td>
158+</tr>
159+<tr>
160+<td>HTC Thunderbolt 4G</td>
161+<td>Huawei Ideos S7</td>
162+<td>LG Optimus Z</td>
163+<td>Motorola Atrix 4G</td>
164+<td>Motorola Bravo</td>
165+</tr>
166+<tr>
167+<td>Motorola Cliq 2 - untested</td>
168+<td>Motorola Defy</td>
169+<td>Motorola Droid 2, Droid 2 Global</td>
170+<td>Motorola Droid Pro (Motorola Pro)</td>
171+<td>Motorola Droid X</td>
172+</tr>
173+<tr>
174+<td>Motorola Xoom</td>
175+<td>POV Mobii Tegra Tablet</td>
176+<td>Samsung Continuum (i400)</td>
177+<td>Samsung Galaxy S (i9000, Captivate,<br />
178+Fascinate, Vibrant, Epic 4G)</td>
179+<td>Samsung Galaxy Tab</td>
180+</tr>
181+<tr>
182+<td>Sharp IS03</td>
183+<td>Sony Ericsson Xperia X10</td>
184+<td>Toshiba AS100</td>
185+<td>Viewsonic gTablet</td>
186+<td>Acer Liquid E</td>
187+</tr>
188+<tr>
189+<td>Acer Liquid (Liquid A1)</td>
190+<td>Archos 101 Internet Tablet</td>
191+<td>Motorola Charm</td>
192+<td>Motorola Droid (Milestone)</td>
193+<td>Samsung Galaxy S 4G</td>
194+</tr>
195+<tr>
196+<td>Samsung Nexus S</td>
197+<td></td>
198+<td></td>
199+<td></td>
200+<td></td>
201+</tr>
202+</tbody>
203+</table>
204+
205+| | | | |
206+|----|----|----|----|
207+| Android SDK emulator | Asus Garmin nuvifone A50 (T-Mobile Garminfone) | Augen GENTouch 78 Tablet | Coby Kyros Internet Tablet (MID7015) |
208+| Geeksphone One, Geeksphone Zero | HTC Aria | HTC ChaCha | HTC Dream (T-Mobile G1, Android Dev Phone 1) |
209+| HTC Droid Eris | HTC Espresso (T-Mobile myTouch 3G Slide) | HTC Hero (T-Mobile G2 Touch) | \|HTC Legend |
210+| HTC Magic (T-Mobile myTouch 3G, T-Mobile G1 Touch) | HTC Salsa | HTC Tattoo | HTC Wildfire |
211+| Huawei Ascend | Huawei Ideos U8150-B (T-Mobile Comet) | Huawei U8110 (T-Mobile Pulse Mini) | \|Huawei U8230 |
212+| LG Ally (Apex) (LG VS740) | LG GW620 (Eve, InTouch Max, LinkMe) | LG Optimus, Optimus M, Optimus T, Optimus S, Optimus V | LG Vortex |
213+| LG P500 | MAG iMiTO iM7 | vMAG iMiTO iM7S | Motorola Backflip |
214+| Motorola Citrus | Motorola Cliq (MB200) | Motorola Dext | Motorola Devour |
215+| Motorola i1 | Motorola Spice XT300 | Motorola Quench XT5 XT502 | Pandigital Novel |
216+| Samsung GT-S5570 Galaxy Mini | Samsung i5500 Galaxy 5 (Corby) | Samsung i5700 Galaxy Portal (Spica) | Samsung i5800 Galaxy 3 |
217+| Samsung i7500 Galaxy | Samsung Intercept | Samsung M900 Moment | Samsung S5830 Galaxy Ace |
218+| Samsung Transform | Sanyo ZIO M6000 | Sony Ericsson Xperia X8 | Sony Ericsson Xperia X10 Mini |
219+| Sony Ericsson Xperia X10 Mini Pro | Superpad 10.2" Tablet PC | Viewsonic ViewPad 7 Tablet | Velocity Micro T103 Cruz tablet |
220+| Vodafone 845 | ZTE Blade | | |
221+
222+List of ARMv6 processors:'''
223+
224+### Playing sounds and videos on the phones
225+
226+Each phone comes with different codecs installed, which means that the native Media Player will be able to play different formats in different phones. Below is a table showing which formats play in the native Media Player of each phone:
227+
228+| Telephone | Android | webm - VP8 | m4v - H.264 | ogv - Theora | mp4 - H.264 | mov - H.264 | avi - RLE | mpg - MPEG-1 | wmv - WM9 | 3gp - MPEG-4 |
229+|----|----|----|----|----|----|----|----|----|----|----|
230+| Emulator | 1.6 | x | x | x | x | x | x | x | x | OK |
231+| Emulator | 2.1 | x | x | x | x | x | x | x | x | OK |
232+| Nexus One | 2.2 | x | OK | x | OK | x | x | x | x | OK |
233+| HTC Desire | 1.6 | x | OK | x | OK | x | x | x | OK | OK |
234+| Toshiba Folio 100 | 2.2 | x | OK | x | OK | x | x | x | OK | OK |
235+| Xperia X10 | 2.1 | x | OK | x | x | x | x | x | OK | OK |
236+| Xperia X8 | 2.2 | x | OK | x | x | x | x | x | x | OK |
237+| HTC Wildfire | 2.1 | x | OK | x | x | x | x | x | x | OK |
238+| HTC Desire HD | 2.2 | x | OK | x | OK | x | x | x | x | OK |
239+| Galaxy Tab | 2.2 | x | OK | x | x | x | x | x | x | OK |
240+| myPhone A210 | 1.6 | x | OK | x | x | x | x | x | x | OK |
241+| Motorola Milestone | 2.1 | x | OK | x | x | x | x | x | OK | ? |
242+| Milestone 2 | 2.2 | x | OK | x | x | x | x | x | sound-only | OK |
243+
244+## Android file system
245+
246+Android recommends to use getApplicationContext().getFilesDir() to obtain the data directory for the application and this routine in my HTC Wildfire returns /data/data/\<package name\>
247+
248+The native libraries of the application are placed in /data/data/\<package\>/lib
249+
250+A good place where we have read and write access and we can create new files and even run files is /data/data/\<package name\>
251+
252+## Creating a new Java Android application
253+
254+This info can be useful for helping implement LCL-CustomDrawn-Android
255+
256+Generic instructions here: <http://developer.android.com/guide/developing/other-ide.html>
257+
258+### Showing/hiding the virtual keyboard
259+
260+See here: <http://android-codes-examples.blogspot.com/2011/11/show-or-hide-soft-keyboard-on-opening.html>
261+
262+To show it:
263+
264+``` java
265+InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
266+imm.toggleSoftInput(InputMethodManager.SHOW_FORCED,0);
267+```
268+
269+and for hiding the keyboard:
270+
271+``` java
272+InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
273+imm.hideSoftInputFromWindow(singleedittext.getWindowToken(),0);
274+```
275+
276+## Android JNI
277+
278+Using JNI (Java Native Interface) you can call most Android SDK APIs and also other Java libraries.
279+
280+### Table of Java types and Pascal JNI types
281+
282+All of the Java types except interfaces can be represented in JNI without problems. For each Java type there is a corresponding VM Type Signature which is utilized in routines such as javaEnvRef^^.GetMethodID. There is also the JNI native type, which is the type declared in the unit lazarus/lcl/interfaces/customdrawn/android/jni.pas and should be the type utilized in JNI code written in Pascal. The Pascal equivalent is provided just for comparison, as one should use the types from jni.pas when writing JNI code.
283+
284+| Java type | VM signature | Type in jni.pas | Pascal equivalent | Description |
285+|----|----|----|----|----|
286+| boolean | Z | jboolean | Boolean | |
287+| byte | B | jbyte | Byte | |
288+| char | C | jchar | Word | |
289+| short | S | jshort | Shortint | |
290+| int | I | jint | Integer | |
291+| long | J | jlong | Int64 | |
292+| float | F | jfloat | Single | |
293+| double | D | jdouble | Double | |
294+| a class, ie: String or InputStream | L\<full class name\> ie: Ljava/lang/String; | jobject | N/A | |
295+| Array, ie: int\[\] | \[\<type-name\> ie: \[I | N/A | | |
296+| A method type | (arg-types)ref-type | JMethodID | N/A | |
297+| void | V | N/A | procedure | |
298+
299+### Example 1: Creating a Java object and calling a Java method
300+
301+Let's say that you want to make Pascal JNI code equivalent to the following Java code:
302+
303+``` java
304+ HttpGet javaRequest = new HttpGet();
305+ URI myURI = new URI("http://magnifier.sourceforge.net/");
306+ javaRequest.setURI(myURI);
307+```
308+
309+First you need to get all Class IDs involved in the process, then get all method IDs which we will use and then make the calls. If the call has parameters, then pass it in an array. The following Pascal native code is equivalent to that Java code above:
310+
311+``` pascal
312+uses jni, customdrawnint;
313+
314+var
315+ javaClass_HttpGet, javaClass_URI: jclass;
316+ javaMethod_HttpGet_new, javaMethod_HttpGet_setURI,
317+ javaMethod_URI_new: jmethodid;
318+ javaRequest, javaURI: jobject;
319+ javaString: jstring;
320+ lParams: array[0..2] of JValue;
321+ lNativeString: PChar;
322+begin
323+ DebugLn(':>LoadHTMLPageViaJNI');
324+ // First call FindClass for all required classes
325+ javaClass_HttpGet := javaEnvRef^^.FindClass(javaEnvRef,
326+ 'org/apache/http/client/methods/HttpGet');
327+ javaClass_URI := javaEnvRef^^.FindClass(javaEnvRef,
328+ 'java/net/URI');
329+
330+ // Now all Method IDs
331+ DebugLn(':LoadHTMLPageViaJNI 1');
332+ javaMethod_HttpGet_new := javaEnvRef^^.GetMethodID(javaEnvRef, javaClass_HttpGet, '<init>', '()V');
333+ javaMethod_HttpGet_setURI := javaEnvRef^^.GetMethodID(javaEnvRef, javaClass_HttpGet, 'setURI', '(Ljava/net/URI;)V');
334+ javaMethod_URI_new := javaEnvRef^^.GetMethodID(javaEnvRef, javaClass_URI, '<init>', '(Ljava/lang/String;)V');
335+
336+ // Create a new instance for the HTTP request object
337+ // HttpGet javaRequest = new HttpGet();
338+ javaRequest := javaEnvRef^^.NewObject(javaEnvRef,
339+ javaClass_HttpGet,
340+ javaMethod_HttpGet_new);
341+
342+ DebugLn(':LoadHTMLPageViaJNI 4 javaRequest='+IntToHex(PtrInt(javaRequest), 8));
343+ // Add a URI for the request object
344+ // URI javaURI = new URI("http://magnifier.sourceforge.net/");
345+ lParams[0].l := javaEnvRef^^.NewStringUTF(javaEnvRef, 'http://magnifier.sourceforge.net');
346+ javaURI := javaEnvRef^^.NewObjectA(javaEnvRef,
347+ javaClass_URI, javaMethod_URI_new, @lParams[0]);
348+ javaEnvRef^^.DeleteLocalRef(javaEnvRef, lParams[0].l);
349+ // javaRequest.setURI(javaURI);
350+ lParams[0].l := javaURI;
351+ javaEnvRef^^.CallVoidMethodA(javaEnvRef, javaRequest,
352+ javaMethod_HttpGet_setURI, @lParams[0]);
353+```
354+
355+### Example 2: Calling a static method
356+
357+Let's say that you want to call the following static method located in the Bass class: <http://jerome.jouvie.free.fr/nativebass/javadoc/org/jouvieje/bass/Bass.html>
358+
359+``` java
360+ public static native int BASS_StreamCreateFile(String file, long offset, long length, int flags);
361+```
362+
363+First you need to get all Class IDs involved in the process, then get the static method ID and then make the call with the parameter in the array:
364+
365+``` pascal
366+uses jni, customdrawnint;
367+
368+var
369+ javaClass_Bass: jclass;
370+ javaMethod_Bass_BASS_StreamCreateFile: jmethodid;
371+ javaString: jstring;
372+ lParams: array[0..3] of JValue;
373+ lRetInt: jint;
374+begin
375+ // First call FindClass for all required classes
376+ javaClass_Bass := javaEnvRef^^.FindClass(javaEnvRef, 'org/jouvieje/bass/Bass');
377+
378+ // Now all Method IDs
379+ javaMethod_Bass_BASS_StreamCreateFile := javaEnvRef^^.GetStaticMethodID(javaEnvRef, javaClass_Bass, 'BASS_StreamCreateFile', '(Ljava/lang/String;JJI)I');
380+
381+ // Make the call
382+ lParams[0].l := javaEnvRef^^.NewStringUTF(javaEnvRef, '/path/to/file');
383+ lParams[1].j := 0; // offset
384+ lParams[2].j := 200; // length
385+ lParams[3].i := 0; // flags
386+ lRetInt := javaEnvRef^^.CallStaticIntMethodA(javaEnvRef, javaClass_Bass, javaMethod_Bass_BASS_StreamCreateFile, @lParams[0]);
387+ javaEnvRef^^.DeleteLocalRef(javaEnvRef, lParams[0].l);
388+```
389+
390+## References
391+
392+- <http://developer.android.com/guide/developing/other-ide.html>
393+- [Tutorial "Lazarus and Android"](https://dl.dropboxusercontent.com/u/3753548/Lazarus%20and%20Android.pdf) (PDF file)
394+
395+---
396+*From the Free Pascal wiki, page "Android Programming", as it stood on 2019-12-16 after a change by Trev, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*

Back to history