|
|
(8 intermediate revisions by 7 users not shown) |
Line 1: |
Line 1: |
| + | {{Platform only|Android|Android|Android}} |
| Go back to [[Android Interface]] | | Go back to [[Android Interface]] |
| | | |
Line 6: |
Line 7: |
| See the page about [[Android4Pascal]], which is the bindings between Pascal programs and the Android Java APIs. | | See the page about [[Android4Pascal]], which is the bindings between Pascal programs and the Android Java APIs. |
| | | |
− | ==Android API Hello World in Pascal==
| |
| | | |
− | Here is an example Pascal application written for Android. It shows how to create controls, receive callback events and how to use the timer.
| |
− |
| |
− | The full directory structure can be download with this svn command:
| |
− |
| |
− | svn co https://p-tools.svn.sourceforge.net/svnroot/p-tools/turbochessclock4android turbochessclock4android
| |
− |
| |
− | [[Image:Simple Android app.png]]
| |
− |
| |
− | Here is the Pascal code from this example:
| |
− |
| |
− | <delphi>
| |
− | {
| |
− | A simple Chess Clock application
| |
− |
| |
− | Author: Felipe Monteiro de Carvalho - 2011
| |
− | License: Public Domain
| |
− | }
| |
− | program turbochessclock4android;
| |
− |
| |
− | {$mode objfpc}{$H+}
| |
− |
| |
− | uses
| |
− | Classes, SysUtils, androidpipescomm, androidview, javalang,
| |
− | androidapp, androidtimer, androidutil;
| |
− |
| |
− | type
| |
− | TEventHandler = class
| |
− | public
| |
− | procedure HandleOnTimer(ASender: TObject);
| |
− | procedure buttonStartClickCallback(v: TView);
| |
− | procedure buttonMoveClickCallback(v: TView);
| |
− | end;
| |
− |
| |
− | var
| |
− | layout: TLinearLayout;
| |
− | params: TLayoutParams;
| |
− | tv, black_label, white_label: TTextView;
| |
− | scroller: TScrollView;
| |
− | btn_move, btn_start: TButton;
| |
− | tp: TTimePicker;
| |
− | WhiteTimeCount: Integer = 0;
| |
− | BlackTimeCount: Integer = 0;
| |
− | MyTimer: TAndroidTimer;
| |
− | MyEventHandler: TEventHandler;
| |
− | IsWhitePlayerMove: Boolean = True;
| |
− |
| |
− | procedure TEventHandler.buttonStartClickCallback(v: TView);
| |
− | begin
| |
− | black_label.setVisibility(VISIBLE);
| |
− | white_label.setVisibility(VISIBLE);
| |
− | btn_move.setVisibility(VISIBLE);
| |
− | //
| |
− | WhiteTimeCount := tp.getCurrentHour() * 60 * 60 + tp.getCurrentMinute() * 60;
| |
− | BlackTimeCount := WhiteTimeCount;
| |
− | //
| |
− | MyTimer.removeCallbacks();
| |
− | MyTimer.postDelayed(100);
| |
− | end;
| |
− |
| |
− | procedure TEventHandler.buttonMoveClickCallback(v: TView);
| |
− | begin
| |
− | IsWhitePlayerMove := not IsWhitePlayerMove;
| |
− | end;
| |
− |
| |
− | procedure TEventHandler.HandleOnTimer(ASender: TObject);
| |
− | var
| |
− | lSeconds, lMinutes, lHours: Integer;
| |
− | begin
| |
− | if IsWhitePlayerMove then
| |
− | begin
| |
− | lSeconds := WhiteTimeCount mod 60;
| |
− | lMinutes := (WhiteTimeCount mod (60 * 60)) div 60;
| |
− | lHours := WhiteTimeCount div (60 * 60);
| |
− | white_label.setText(Format('White %d:%d:%d', [lHours, lMinutes, lSeconds]));
| |
− | //
| |
− | if WhiteTimeCount = 0 then Exit;
| |
− | Dec(WhiteTimeCount);
| |
− | end
| |
− | else
| |
− | begin
| |
− | lSeconds := BlackTimeCount mod 60;
| |
− | lMinutes := (BlackTimeCount mod (60 * 60)) div 60;
| |
− | lHours := BlackTimeCount div (60 * 60);
| |
− | black_label.setText(Format('Black %d:%d:%d', [lHours, lMinutes, lSeconds]));
| |
− | //
| |
− | if BlackTimeCount = 0 then Exit;
| |
− | Dec(BlackTimeCount);
| |
− | end;
| |
− | //
| |
− | MyTimer.removeCallbacks();
| |
− | // Note that this has a low precision, but it enough for this simple app
| |
− | // A more precise app would keep another time count instead of just using Dec
| |
− | // at each timer call
| |
− | MyTimer.postDelayed(1000);
| |
− | end;
| |
− |
| |
− | begin
| |
− | // Here add any initialization.
| |
− | // Any initialization code will be run inside Activity.onCreate,
| |
− | // so keep it as short as possible!
| |
− | // It should mostly contain GUI initialization
| |
− | // User interface
| |
− | MyEventHandler := TEventHandler.Create;
| |
− |
| |
− | // Prepares the UI of the program
| |
− | layout := TLinearLayout.Create;
| |
− | params := TLayoutParams.Create(androidview.FILL_PARENT, androidview.FILL_PARENT);
| |
− | layout.setLayoutParams(params);
| |
− | params.Free;
| |
− | layout.setOrientation(androidview.VERTICAL);
| |
− |
| |
− | // Game UI
| |
− |
| |
− | black_label := TTextView.Create;
| |
− | black_label.setText('Black time:');
| |
− | black_label.setVisibility(GONE);
| |
− | black_label.setTextSize(COMPLEX_UNIT_PX, 40);
| |
− | layout.addView(black_label);
| |
− |
| |
− | white_label := TTextView.Create;
| |
− | white_label.setText('White time:');
| |
− | white_label.setVisibility(GONE);
| |
− | white_label.setTextSize(COMPLEX_UNIT_PX, 40);
| |
− | layout.addView(white_label);
| |
− |
| |
− | btn_move := TButton.Create;
| |
− | btn_move.setText('Move finished!');
| |
− | btn_move.setOnClickListener(@MyEventHandler.buttonMoveClickCallback);
| |
− | btn_move.setVisibility(GONE);
| |
− | layout.addView(btn_move);
| |
− |
| |
− | // Config UI
| |
− |
| |
− | tv := TTextView.Create;
| |
− | tv.setText('Please select how much to give to the players and press "Start Game":');
| |
− | layout.addView(tv);
| |
− |
| |
− | tp := TTimePicker.Create;
| |
− | tp.setIs24HourView(True);
| |
− | tp.setCurrentHour(0);
| |
− | tp.setCurrentMinute(30);
| |
− | layout.addView(tp);
| |
− |
| |
− | btn_start := TButton.Create;
| |
− | btn_start.setText('Start game!');
| |
− | btn_start.setOnClickListener(@MyEventHandler.buttonStartClickCallback);
| |
− | layout.addView(btn_start);
| |
− |
| |
− | // And also allow the user to scroll the UI if it is larger then the screen width
| |
− | // Scrolling takes place only horizontally
| |
− |
| |
− | scroller := TScrollView.Create;
| |
− | scroller.addView(layout);
| |
− |
| |
− | Activity.setContentView(scroller);
| |
− |
| |
− | MyTimer := TAndroidTimer.Create;
| |
− | MyTimer.OnTimer := @MyEventHandler.HandleOnTimer;
| |
− |
| |
− | // Now tell Java that the initialization has finished
| |
− | vAndroidPipesComm.onCreateFinished();
| |
− | // Here you can add any other initialization,
| |
− | // specially non-GUI code
| |
− |
| |
− | // Now we block our execution waiting for callbacks from Java
| |
− | vAndroidPipesComm.MessageLoop();
| |
− | end.
| |
− | </delphi>
| |
− |
| |
− | ===Compiling the example project in Linux===
| |
− |
| |
− | 1> Get a working arm-linux cross-compiler which generates ARMv5 eabi with softfloat (as many phones like HTC Wildfire have no FPU)
| |
− |
| |
− | To do this one can download an unofficial build of FPC 2.5.1 from here:
| |
− |
| |
− | http://sourceforge.net/projects/p-tools/files/Free%20Pascal%20for%20ARM/ Compiled for ARMv5 eabi with softfloat.
| |
− |
| |
− | Or an older FPC 2.4.2
| |
− |
| |
− | http://members.yline.com/~tom_at_work/fpc-2.4.2.UNOFFICIAL.arm-linux.tar Compiled for ARMv5 eabi with softfloat.
| |
− |
| |
− | Or build your own. There are instructions here: [[Setup_Cross_Compile_For_ARM]]
| |
− |
| |
− | 2> Install the Android SDK. Instructions here: [[Android_Interface/Using_the_Android_SDK%2C_Emulator_and_Phones#Using_the_Android_SDK]]
| |
− |
| |
− | 3> Install ant, for example in Mandriva Linux:
| |
− |
| |
− | urpmi ant
| |
− |
| |
− | 4> Open the project turbochessclock/turbochessclock4android.lpi in Lazarus and build it
| |
− |
| |
− | 5> Build the APK file in debug mode
| |
− |
| |
− | ant debug
| |
− |
| |
− | 6> Connect your phone and make sure you can connect to it via ADB. More info here: [[Android_Interface/Using_the_Android_SDK%2C_Emulator_and_Phones#Recognition_of_devices_under_Linux]]
| |
− |
| |
− | 7> Install the APK file in your phone via ADB or whatever other method you prefer:
| |
− |
| |
− | ../android-sdk-linux_x86/tools/adb install android/bin/TurboChessClock4Android-debug.apk
| |
− |
| |
− | If the package is already installed you need need to do this instead:
| |
− |
| |
− | ../android-sdk-linux_x86/tools/adb uninstall com.pascal.turbochessclock
| |
− | ../android-sdk-linux_x86/tools/adb install android/bin/TurboChessClock4Android-debug.apk
| |
| | | |
| ==Manifest configuration== | | ==Manifest configuration== |
Line 218: |
Line 13: |
| ===Control the program restart=== | | ===Control the program restart=== |
| | | |
− | By default the program will restart on orientation change, on keyboard change, and in a lot of other cases. This is usually unwanted. To disable program restart o keyboard showing and orientation changed add this to the manifest file: | + | By default the program will restart on orientation change, on keyboard change, and in a lot of other cases. This is usually unwanted. To disable program restart on keyboard showing and orientation changed add this to the manifest file: |
| | | |
− | <code> | + | <syntaxhighlight lang=pascal> |
| <activity | | <activity |
| ... | | ... |
| android:configChanges="orientation|keyboardHidden" | | android:configChanges="orientation|keyboardHidden" |
− | </code> | + | </syntaxhighlight> |
| | | |
| See also: | | See also: |
Line 244: |
Line 39: |
| ====Timer example==== | | ====Timer example==== |
| | | |
− | <delphi> | + | <syntaxhighlight lang=pascal> |
| program turbochessclock4android; | | program turbochessclock4android; |
| | | |
Line 282: |
Line 77: |
| // ... | | // ... |
| end. | | end. |
− | </delphi> | + | </syntaxhighlight> |
| + | |
| + | [[Category:Android]] |