LCL-Android example: Starts adding sqlite support

git-svn-id: trunk@39427 -
This commit is contained in:
sekelsenmat 2012-12-01 14:09:43 +00:00
parent 614327b055
commit d67e97dbd5
14 changed files with 659 additions and 63 deletions

3
.gitattributes vendored
View File

@ -3906,6 +3906,9 @@ examples/androidlcl/nonandroidtest.lpr svneol=native#text/pascal
examples/androidlcl/runwindowsapp.bat svneol=native#text/plain
examples/androidlcl/secondform.lfm svneol=native#text/plain
examples/androidlcl/secondform.pas svneol=native#text/pascal
examples/androidlcl/sqliteform.lfm svneol=native#text/plain
examples/androidlcl/sqliteform.pas svneol=native#text/plain
examples/androidlcl/sqlitejniandroid.pas svneol=native#text/plain
examples/autosize/childsizinglayout/childsizinglayout.lpi svneol=native#text/plain
examples/autosize/childsizinglayout/childsizinglayout.lpr svneol=native#text/plain
examples/autosize/childsizinglayout/mainunit.lfm svneol=native#text/plain

View File

@ -7,6 +7,7 @@
<uses-permission android:name="android.permission.SEND_SMS" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<supports-screens android:smallScreens="true" android:normalScreens="true" android:largeScreens="true" android:anyDensity="true" />
<uses-sdk android:minSdkVersion="8" android:targetSdkVersion="8" />
<application android:label="@string/app_name"

View File

@ -1,9 +1,9 @@
REM Adjust these paths to yours
SET PATH=C:\Programas\android-sdk\tools;C:\Programas\android-sdk\platform-tools\;C:\Progra~1\Java\jdk1.6.0_20\bin
SET PATH=C:\Programas\android-sdk\tools;C:\Programas\android-sdk\platform-tools\;C:\Progra~1\Java\jdk1.6.0_37\bin
SET APP_NAME=androidlcltest
SET ANDROID_HOME=C:\Programas\android-sdk
SET APK_SDK_PLATFORM=C:\Programas\android-sdk\platforms\android-8
SET APK_PROJECT_PATH=F:\Programas\lazarussvn\examples\androidlcl\android
SET APK_PROJECT_PATH=C:\Programas\lazarussvn\examples\androidlcl\android
REM Create necessary directory Structure
mkdir bin

View File

@ -1,5 +1,5 @@
REM Adjust these paths to yours
SET PATH=C:\Programas\android-sdk\tools;C:\Programas\android-sdk\platform-tools\;C:\Progra~1\Java\jdk1.6.0_20\bin
SET PATH=C:\Programas\android-sdk\tools;C:\Programas\android-sdk\platform-tools\;C:\Progra~1\Java\jdk1.6.0_37\bin
SET APP_NAME=androidlcltest
SET ANDROID_HOME=C:\Programas\android-sdk
SET APK_SDK_PLATFORM=C:\Programas\android-sdk\platforms\android-8

View File

@ -114,12 +114,15 @@
<FormatVersion Value="1"/>
</local>
</RunParams>
<RequiredPackages Count="1">
<RequiredPackages Count="2">
<Item1>
<PackageName Value="LCL"/>
<PackageName Value="FCL"/>
</Item1>
<Item2>
<PackageName Value="LCL"/>
</Item2>
</RequiredPackages>
<Units Count="5">
<Units Count="7">
<Unit0>
<Filename Value="androidlcltest.lpr"/>
<IsPartOfProject Value="True"/>
@ -128,7 +131,7 @@
<Unit1>
<Filename Value="mainform.pas"/>
<IsPartOfProject Value="True"/>
<ComponentName Value="Form1"/>
<ComponentName Value="form1"/>
<HasResources Value="True"/>
<ResourceBaseClass Value="Form"/>
<UnitName Value="mainform"/>
@ -149,16 +152,29 @@
<Filename Value="android/AndroidManifest.xml"/>
<IsPartOfProject Value="True"/>
</Unit4>
<Unit5>
<Filename Value="sqlitejniandroid.pas"/>
<IsPartOfProject Value="True"/>
<UnitName Value="sqlitejniandroid"/>
</Unit5>
<Unit6>
<Filename Value="sqliteform.pas"/>
<IsPartOfProject Value="True"/>
<ComponentName Value="formSqlite"/>
<HasResources Value="True"/>
<ResourceBaseClass Value="Form"/>
<UnitName Value="sqliteform"/>
</Unit6>
</Units>
</ProjectOptions>
<CompilerOptions>
<Version Value="11"/>
<Target>
<Filename Value="android/libs/armeabi/liblclapp.so"/>
<Filename Value="android/libs/armeabi/liblclapp"/>
</Target>
<SearchPaths>
<IncludeFiles Value="$(ProjOutDir)"/>
<Libraries Value="../../../android-ndk-r7/platforms/android-8/arch-arm/usr/lib;../../../android-ndk-r7/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86/lib/gcc/arm-linux-androideabi/4.4.3"/>
<Libraries Value="../../../android-ndk-r8c/platforms/android-8/arch-arm/usr/lib;../../../android-ndk-r8c/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86/lib/gcc/arm-linux-androideabi/4.4.3;../../../android-ndk-r8c/toolchains/arm-linux-androideabi-4.4.3/prebuilt/windows/lib/gcc/arm-linux-androideabi/4.4.3"/>
<UnitOutputDirectory Value="lib/$(TargetCPU)-$(TargetOS)"/>
</SearchPaths>
<CodeGeneration>

View File

@ -3,10 +3,8 @@ library androidlcltest;
{$mode objfpc}{$H+}
uses
customdrawnint,
Interfaces,
Forms,
mainform, secondform, customdrawn_android, customdrawndrawers;
customdrawnint, Interfaces, Forms, mainform, secondform, sqlitejniandroid,
customdrawn_android, customdrawndrawers, sqliteform;
exports
Java_com_pascal_lclproject_LCLActivity_LCLOnTouch name 'Java_com_pascal_lcltest_LCLActivity_LCLOnTouch',
@ -27,6 +25,7 @@ begin
Application.Initialize;
Application.CreateForm(TForm1, Form1);
Application.CreateForm(TForm2, Form2);
Application.CreateForm(TFormSqlite, formSqlite);
Application.Run;
end;

View File

@ -1,9 +1,9 @@
object Form1: TForm1
object form1: Tform1
Left = 161
Height = 257
Top = 137
Width = 220
Caption = 'Form1'
Caption = 'form1'
ClientHeight = 257
ClientWidth = 220
OnClick = FormClick
@ -43,9 +43,9 @@ object Form1: TForm1
end
object CheckBox1: TCheckBox
Left = 72
Height = 17
Height = 19
Top = 40
Width = 71
Width = 78
Caption = 'CheckBox1'
TabOrder = 3
end
@ -69,9 +69,9 @@ object Form1: TForm1
end
object Label1: TLabel
Left = 24
Height = 14
Height = 15
Top = 226
Width = 32
Width = 34
Caption = 'Label1'
Font.Color = clBlue
ParentColor = False
@ -88,11 +88,11 @@ object Form1: TForm1
end
object ComboBox1: TComboBox
Left = 72
Height = 21
Height = 23
Top = 128
Width = 140
AutoSize = False
ItemHeight = 13
ItemHeight = 15
Items.Strings = (
'Item1'
'Item2'

View File

@ -16,9 +16,9 @@ uses
type
TSubControl = class;
{ TForm1 }
{ Tform1 }
TForm1 = class(TForm)
Tform1 = class(TForm)
Button1: TButton;
Button2: TButton;
Button3: TButton;
@ -74,11 +74,11 @@ type
end;
var
Form1: TForm1;
form1: Tform1;
implementation
uses secondform,
uses secondform, sqliteform,
ctypes, //android_sockets,
{$ifdef Android}
jni,
@ -122,40 +122,40 @@ end;
{$R *.lfm}
{ TForm1 }
{ Tform1 }
procedure TForm1.FormClick(Sender: TObject);
procedure Tform1.FormClick(Sender: TObject);
begin
DebugLn(Format('Form click #%d', [ClickCounter]));
Inc(ClickCounter);
// Invalidate;
end;
procedure TForm1.Arrow1Click(Sender: TObject);
procedure Tform1.Arrow1Click(Sender: TObject);
begin
Caption := 'Clicked Arrow';
DebugLn('Clicked Arrow');
end;
procedure TForm1.Arrow1MouseDown(Sender: TObject; Button: TMouseButton;
procedure Tform1.Arrow1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
DebugLn(Format('Arrow Mouse Down X=%d Y=%d', [X, Y]));
end;
procedure TForm1.Arrow1MouseMove(Sender: TObject; Shift: TShiftState; X,
procedure Tform1.Arrow1MouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
begin
DebugLn(Format('Arrow Mouse Move X=%d Y=%d', [X, Y]));
end;
procedure TForm1.Arrow1MouseUp(Sender: TObject; Button: TMouseButton;
procedure Tform1.Arrow1MouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
DebugLn(Format('Arrow Mouse Up X=%d Y=%d', [X, Y]));
end;
procedure TForm1.btnShowInfoClick(Sender: TObject);
procedure Tform1.btnShowInfoClick(Sender: TObject);
//var
// i: Integer;
begin
@ -166,7 +166,7 @@ begin
Device.Vibrate(2000);
end;
procedure TForm1.Button1Click(Sender: TObject);
procedure Tform1.Button1Click(Sender: TObject);
var
sqliteDLL : Pointer;
begin
@ -184,31 +184,31 @@ begin
// Self.AutoAdjustLayout(lapAutoAdjustWithoutHorizontalScrolling, 96, 150, 220, 600);
end;
procedure TForm1.Button1KeyDown(Sender: TObject; var Key: Word;
procedure Tform1.Button1KeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
begin
DebugLn('[TForm1.Button1KeyDown] '+ LCLProc.DbgsVKCode(Key));
// Caption := 'KeyDown ' + LCLProc.DbgsVKCode(Key);
end;
procedure TForm1.Button1KeyPress(Sender: TObject; var Key: char);
procedure Tform1.Button1KeyPress(Sender: TObject; var Key: char);
begin
DebugLn('KeyPress: ' + Key);
end;
procedure TForm1.Button1KeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
procedure Tform1.Button1KeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
begin
DebugLn('[TForm1.Button1KeyUp] '+ LCLProc.DbgsVKCode(Key));
// Caption := 'KeyUp ' + LCLProc.DbgsVKCode(Key);
end;
procedure TForm1.Button1UTF8KeyPress(Sender: TObject; var UTF8Key: TUTF8Char);
procedure Tform1.Button1UTF8KeyPress(Sender: TObject; var UTF8Key: TUTF8Char);
begin
DebugLn('UTF8KeyPress: ' + UTF8Key);
Caption := UTF8Key;
end;
procedure TForm1.Button2Click(Sender: TObject);
procedure Tform1.Button2Click(Sender: TObject);
begin
Application.OnMessageDialogFinished := @HandleMessageDialogFinished;
DebugLn('Button2Click A');
@ -217,13 +217,14 @@ begin
DebugLn('Button2Click B');
end;
procedure TForm1.Button3Click(Sender: TObject);
procedure Tform1.Button3Click(Sender: TObject);
begin
Form2.Show;
//Form2.Show;
formsqlite.Show;
DebugLn('Button3Click');
end;
procedure TForm1.FormCreate(Sender: TObject);
procedure Tform1.FormCreate(Sender: TObject);
begin
SubControl := TSubControl.Create(Self);
SubControl.Left := 40;
@ -235,13 +236,13 @@ begin
OnListViewDialogResult := @MyOnListViewDialogResult;
end;
procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
procedure Tform1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
begin
DebugLn(Format('MouseMove x=%d y=%d', [x, y]));
end;
procedure TForm1.FormPaint(Sender: TObject);
procedure Tform1.FormPaint(Sender: TObject);
var
lPoints: array[0..2] of TPoint;
begin
@ -259,17 +260,17 @@ begin
Canvas.Rectangle(200, 200, 300, 300);}
end;
procedure TForm1.MenuItem1Click(Sender: TObject);
procedure Tform1.MenuItem1Click(Sender: TObject);
begin
DebugLn('[TForm1.MenuItem1Click]');
end;
procedure TForm1.HandleMessageDialogFinished(Sender: TObject; AResult: Integer);
procedure Tform1.HandleMessageDialogFinished(Sender: TObject; AResult: Integer);
begin
DebugLn(Format('[TForm1.HandleMessageDialogFinished] AResult=%d', [AResult]));
end;
procedure TForm1.SocketProc;
procedure Tform1.SocketProc;
const
RCVBUFSIZE = 64;
(*var
@ -330,7 +331,7 @@ begin
}//-- end main --//*)
end;
function TForm1.LoadHTMLPageViaJNI(AURL: string): string;
function Tform1.LoadHTMLPageViaJNI(AURL: string): string;
{$ifdef Android}
var
javaClass_DefaultHttpClient, javaClass_AbstractHttpClient, javaClass_HttpGet,
@ -466,7 +467,7 @@ begin
{$endif}
end;
procedure TForm1.MyOnListViewDialogResult(ASelectedItem: Integer);
procedure Tform1.MyOnListViewDialogResult(ASelectedItem: Integer);
begin
DebugLn(Format('[MyOnListViewDialogResult] ASelectedItem=%d', [ASelectedItem]));
end;

View File

@ -46,6 +46,7 @@
</CompilerMessages>
<CompilerPath Value="$(CompPath)"/>
</Other>
<LCLWidgetType Value="customdrawn"/>
</CompilerOptions>
</Item2>
<Item3 Name="NotCustomDrawn">
@ -99,6 +100,7 @@
</CompilerMessages>
<CompilerPath Value="$(CompPath)"/>
</Other>
<LCLWidgetType Value="cocoa"/>
</CompilerOptions>
</Item4>
</BuildModes>
@ -117,7 +119,7 @@
<PackageName Value="LCL"/>
</Item1>
</RequiredPackages>
<Units Count="3">
<Units Count="4">
<Unit0>
<Filename Value="nonandroidtest.lpr"/>
<IsPartOfProject Value="True"/>
@ -139,6 +141,14 @@
<ResourceBaseClass Value="Form"/>
<UnitName Value="secondform"/>
</Unit2>
<Unit3>
<Filename Value="sqliteform.pas"/>
<IsPartOfProject Value="True"/>
<ComponentName Value="Form3"/>
<HasResources Value="True"/>
<ResourceBaseClass Value="Form"/>
<UnitName Value="sqliteform"/>
</Unit3>
</Units>
</ProjectOptions>
<CompilerOptions>
@ -150,17 +160,13 @@
<IncludeFiles Value="$(ProjOutDir)"/>
<UnitOutputDirectory Value="lib/$(TargetCPU)-$(TargetOS)"/>
</SearchPaths>
<Linking>
<Debugging>
<DebugInfoType Value="dsDwarf2"/>
</Debugging>
</Linking>
<Other>
<CompilerMessages>
<UseMsgFile Value="True"/>
</CompilerMessages>
<CompilerPath Value="$(CompPath)"/>
</Other>
<LCLWidgetType Value="customdrawn"/>
</CompilerOptions>
<Debugging>
<Exceptions Count="3">

View File

@ -4,7 +4,8 @@ program nonandroidtest;
uses
Interfaces, // this includes the LCL widgetset
Forms, mainform, secondform, customdrawndrawers, customdrawn_android;
Forms, mainform, secondform, sqliteform, customdrawndrawers,
customdrawn_android;
{$R *.res}

View File

@ -18,7 +18,7 @@ object Form2: TForm2
end
object textDest: TEdit
Left = 8
Height = 21
Height = 23
Top = 56
Width = 80
OnExit = textDestExit
@ -1794,9 +1794,9 @@ object Form2: TForm2
end
object labelSensorData: TLabel
Left = 8
Height = 14
Height = 15
Top = 168
Width = 60
Width = 62
Caption = 'Sensor Data'
ParentColor = False
end
@ -1820,15 +1820,15 @@ object Form2: TForm2
end
object Label1: TLabel
Left = 10
Height = 14
Height = 15
Top = 88
Width = 50
Width = 51
Caption = 'SMS Text:'
ParentColor = False
end
object textBody: TEdit
Left = 8
Height = 21
Height = 23
Top = 104
Width = 80
TabOrder = 5
@ -1845,9 +1845,9 @@ object Form2: TForm2
end
object Label2: TLabel
Left = 8
Height = 14
Height = 15
Top = 32
Width = 38
Width = 44
Caption = 'Number'
ParentColor = False
end

View File

@ -0,0 +1,51 @@
object formSqlite: TformSqlite
Left = 119
Height = 240
Top = 244
Width = 320
Caption = 'formSqlite'
ClientHeight = 240
ClientWidth = 320
LCLVersion = '1.1'
object Button1: TButton
Left = 8
Height = 25
Top = 8
Width = 75
Caption = 'Connect'
OnClick = Button1Click
TabOrder = 0
end
object DBEdit1: TDBEdit
Left = 8
Height = 23
Top = 104
Width = 80
DataSource = SqliteDatasource
CharCase = ecNormal
MaxLength = 0
TabOrder = 1
end
object DBNavigator1: TDBNavigator
Left = 8
Height = 25
Top = 64
Width = 241
BevelOuter = bvNone
ChildSizing.EnlargeHorizontal = crsScaleChilds
ChildSizing.EnlargeVertical = crsScaleChilds
ChildSizing.ShrinkHorizontal = crsScaleChilds
ChildSizing.ShrinkVertical = crsScaleChilds
ChildSizing.Layout = cclLeftToRightThenTopToBottom
ChildSizing.ControlsPerLine = 100
ClientHeight = 25
ClientWidth = 241
DataSource = SqliteDatasource
Options = []
TabOrder = 2
end
object SqliteDatasource: TDatasource
left = 144
top = 16
end
end

View File

@ -0,0 +1,58 @@
unit sqliteform;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, db, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
DbCtrls;
type
{ TformSqlite }
TformSqlite = class(TForm)
Button1: TButton;
SqliteDatasource: TDatasource;
DBEdit1: TDBEdit;
DBNavigator1: TDBNavigator;
procedure Button1Click(Sender: TObject);
private
{ private declarations }
public
{ public declarations }
end;
var
formSqlite: TformSqlite;
implementation
{$ifdef CPUARM}
uses sqlitejniandroid;
{$endif}
{$R *.lfm}
{ TformSqlite }
procedure TformSqlite.Button1Click(Sender: TObject);
{$ifdef CPUARM}
var
sqlitedb: TSqliteJNIDataset;
{$endif}
begin
{$ifdef CPUARM}
sqlitedb := TSqliteJNIDataset.Create(Self);
//SqliteDatasource.DataSet := sqlitedb;
sqlitedb.FileName := '/sdcard/database.db';
sqlitedb.TableName := 'TestTable';
sqlitedb.FieldDefs.Add('FirstFieldStr', ftString);
sqlitedb.FieldDefs.Add('SecondFieldInt', ftInteger);
sqlitedb.Open();
{$endif}
end;
end.

View File

@ -0,0 +1,460 @@
unit sqlitejniandroid;
{
This is TSqlite3Dataset, a TDataset descendant class for use with fpc compiler
Copyright (C) 2004 Luiz Américo Pereira Câmara
Email: pascalive@bol.com.br
This library is free software; you can redistribute it and/or modify it
under the terms of the GNU Library General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at your
option) any later version with the following modification:
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent modules,and
to copy and distribute the resulting executable under terms of your choice,
provided that you also meet, for each linked independent module, the terms
and conditions of the license of that module. An independent module is a
module which is not derived from or based on this library. If you modify
this library, you may extend this exception to your version of the library,
but you are not obligated to do so. If you do not wish to do so, delete this
exception statement from your version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
for more details.
You should have received a copy of the GNU Library General Public License
along with this library; if not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
}
{$mode objfpc}
{$H+}
{.$Define DEBUG_SQLITEDS}
interface
uses
Classes, SysUtils, CustomSqliteDS,
jni, customdrawnint;
type
{ TSqliteJNIDataset }
TSqliteJNIDataset = class(TCustomSqliteDataset)
private
// Java Classes
FSqliteClosableClass, FSQLiteDatabaseClass: JClass;
// Java Methods
FSqliteClosable_Close: JMethodID;
FSqliteDatabase_ExecSQLMethod, FSqliteDatabase_openOrCreateDatabase,
FSqliteDatabase_getVersion: JMethodID;
// Java Objects
AndroidDB: jobject; // SQLiteDatabase
procedure FindJavaClassesAndMethods;
protected
procedure BuildLinkedList; override;
function GetLastInsertRowId: Int64; override;
function GetRowsAffected:Integer; override;
procedure InternalCloseHandle; override;
function InternalGetHandle: Pointer; override;
procedure RetrieveFieldDefs; override;
function SqliteExec(ASQL: PChar; ACallback: TSqliteCdeclCallback; Data: Pointer): Integer; override;
public
procedure ExecuteDirect(const ASQL: String); override;
function QuickQuery(const ASQL: String; const AStrList: TStrings; FillObjects: Boolean): String; override;
function ReturnString: String; override;
class function SqliteVersion: String; override;
end;
implementation
uses
db, strutils, lclproc;
{
Java code example
Docs: http://developer.android.com/reference/android/database/sqlite/SQLiteDatabase.html
SQLiteDatabase db = openOrCreateDatabase(Preferences.DB_NAME, Context.MODE_PRIVATE, null);
db.execSQL("CREATE TABLE IF NOT EXISTS data (id INTEGER PRIMARY KEY, value VARCHAR)");
Cursor dbResult = db.rawQuery("SELECT value FROM data", null);
// do sometning with cursors
dbResult.close();
db.close();
}
function SqliteCode2Str(Code: Integer): String;
begin
{case Code of
SQLITE_OK :} Result := 'SQLITE_OK';
{SQLITE_ERROR : Result := 'SQLITE_ERROR';
SQLITE_INTERNAL : Result := 'SQLITE_INTERNAL';
SQLITE_PERM : Result := 'SQLITE_PERM';
SQLITE_ABORT : Result := 'SQLITE_ABORT';
SQLITE_BUSY : Result := 'SQLITE_BUSY';
SQLITE_LOCKED : Result := 'SQLITE_LOCKED';
SQLITE_NOMEM : Result := 'SQLITE_NOMEM';
SQLITE_READONLY : Result := 'SQLITE_READONLY';
SQLITE_INTERRUPT : Result := 'SQLITE_INTERRUPT';
SQLITE_IOERR : Result := 'SQLITE_IOERR';
SQLITE_CORRUPT : Result := 'SQLITE_CORRUPT';
SQLITE_NOTFOUND : Result := 'SQLITE_NOTFOUND';
SQLITE_FULL : Result := 'SQLITE_FULL';
SQLITE_CANTOPEN : Result := 'SQLITE_CANTOPEN';
SQLITE_PROTOCOL : Result := 'SQLITE_PROTOCOL';
SQLITE_EMPTY : Result := 'SQLITE_EMPTY';
SQLITE_SCHEMA : Result := 'SQLITE_SCHEMA';
SQLITE_TOOBIG : Result := 'SQLITE_TOOBIG';
SQLITE_CONSTRAINT : Result := 'SQLITE_CONSTRAINT';
SQLITE_MISMATCH : Result := 'SQLITE_MISMATCH';
SQLITE_MISUSE : Result := 'SQLITE_MISUSE';
SQLITE_NOLFS : Result := 'SQLITE_NOLFS';
SQLITE_AUTH : Result := 'SQLITE_AUTH';
SQLITE_FORMAT : Result := 'SQLITE_FORMAT';
SQLITE_RANGE : Result := 'SQLITE_RANGE';
SQLITE_ROW : Result := 'SQLITE_ROW';
SQLITE_NOTADB : Result := 'SQLITE_NOTADB';
SQLITE_DONE : Result := 'SQLITE_DONE';
else
Result := 'Unknown Return Value';
end; }
end;
function GetAutoIncValue(NextValue: Pointer; Columns: Integer; ColumnValues: PPChar; ColumnNames: PPChar): Integer; cdecl;
var
CodeError, TempInt: Integer;
begin
TempInt := 0;
if ColumnValues[0] <> nil then
begin
Val(String(ColumnValues[0]), TempInt, CodeError);
if CodeError <> 0 then
DatabaseError('TSqlite3Dataset: Error trying to get last autoinc value');
end;
Integer(NextValue^) := Succ(TempInt);
Result := 1;
end;
{ TSqlite3Dataset }
function TSqliteJNIDataset.SqliteExec(ASQL: PChar; ACallback: TSqliteCdeclCallback; Data: Pointer): Integer;
var
// array for the parameters
lParams: array[0..2] of JValue;
lJavaString: JString;
begin
DebugLn('[TSqliteJNIDataset.SqliteExec] ' + StrPas(ASQL));
{// void execSQL(String sql)
// preparations
lJavaString :=javaEnvRef^^.NewStringUTF(javaEnvRef, ASQL);
lParams[0].l := lJavaString;
// Call the method
javaEnvRef^^.CallVoidMethodA(javaEnvRef, AndroidDB, lExecSQLMethod, @lParams[0]);
// clean up
javaEnvRef^^.DeleteLocalRef(javaEnvRef, lJavaString);}
end;
procedure TSqliteJNIDataset.InternalCloseHandle;
begin
DebugLn('[TSqliteJNIDataset.InternalCloseHandle]');
// void android.database.sqlite.SQLiteClosable->close()
javaEnvRef^^.CallVoidMethod(javaEnvRef, AndroidDB, FSqliteClosable_close);
//javaEnvRef^^.DeleteLocalRef(javaEnvRef, AndroidDB);
//f/sqlite3_close(FSqliteHandle);
FSqliteHandle := nil;
//todo:handle return data
end;
function TSqliteJNIDataset.InternalGetHandle: Pointer;
const
CheckFileSql = 'Select Name from sqlite_master LIMIT 1';
var
// array for the parameters
lParams: array[0..2] of JValue;
lJavaString: JString;
begin
DebugLn('[TSqliteJNIDataset.InternalGetHandle]');
FindJavaClassesAndMethods();
// static SQLiteDatabase openOrCreateDatabase(String path, SQLiteDatabase.CursorFactory factory)
// preparations
lJavaString :=javaEnvRef^^.NewStringUTF(javaEnvRef, PChar(FFileName));
lParams[0].l := lJavaString;
lParams[1].l := nil;
// Call the method
AndroidDB := javaEnvRef^^.CallStaticObjectMethodA(javaEnvRef, FSqliteDatabaseClass, FSqliteDatabase_openOrCreateDatabase, @lParams[0]);
// clean up
javaEnvRef^^.DeleteLocalRef(javaEnvRef, lJavaString);
end;
procedure TSqliteJNIDataset.RetrieveFieldDefs;
var
vm: Pointer;
ColumnStr: String;
i, ColumnCount, DataSize: Integer;
AType: TFieldType;
begin
DebugLn('[TSqliteJNIDataset.RetrieveFieldDefs]');
{ FAutoIncFieldNo := -1;
FieldDefs.Clear;
FReturnCode := sqlite3_prepare(FSqliteHandle, PChar(FEffectiveSQL), -1, @vm, nil);
if FReturnCode <> SQLITE_OK then
DatabaseError(ReturnString, Self);
sqlite3_step(vm);
ColumnCount := sqlite3_column_count(vm);
//Prepare the array of pchar2sql functions
SetLength(FGetSqlStr, ColumnCount);
for i := 0 to ColumnCount - 1 do
begin
DataSize := 0;
ColumnStr := UpperCase(String(sqlite3_column_decltype(vm, i)));
if (ColumnStr = 'INTEGER') or (ColumnStr = 'INT') then
begin
if AutoIncrementKey and (UpperCase(String(sqlite3_column_name(vm, i))) = UpperCase(PrimaryKey)) then
begin
AType := ftAutoInc;
FAutoIncFieldNo := i;
end
else
AType := ftInteger;
end else if Pos('VARCHAR', ColumnStr) = 1 then
begin
AType := ftString;
DataSize := StrToIntDef(Trim(ExtractDelimited(2, ColumnStr, ['(', ')'])), DefaultStringSize);
end else if Pos('BOOL', ColumnStr) = 1 then
begin
AType := ftBoolean;
end else if Pos('AUTOINC', ColumnStr) = 1 then
begin
AType := ftAutoInc;
if FAutoIncFieldNo = -1 then
FAutoIncFieldNo := i;
end else if (Pos('FLOAT', ColumnStr) = 1) or (Pos('NUMERIC', ColumnStr) = 1) then
begin
AType := ftFloat;
end else if (ColumnStr = 'DATETIME') then
begin
AType := ftDateTime;
end else if (ColumnStr = 'DATE') then
begin
AType := ftDate;
end else if (ColumnStr = 'LARGEINT') or (ColumnStr = 'BIGINT') then
begin
AType := ftLargeInt;
end else if (ColumnStr = 'TIME') then
begin
AType := ftTime;
end else if (ColumnStr = 'TEXT') then
begin
AType := ftMemo;
end else if (ColumnStr = 'CURRENCY') then
begin
AType := ftCurrency;
end else if (ColumnStr = 'WORD') then
begin
AType := ftWord;
end else if (ColumnStr = '') then
begin
case sqlite3_column_type(vm, i) of
SQLITE_INTEGER:
AType := ftInteger;
SQLITE_FLOAT:
AType := ftFloat;
else
begin
AType := ftString;
DataSize := DefaultStringSize;
end;
end;
end else
begin
AType := ftString;
DataSize := DefaultStringSize;
end;
FieldDefs.Add(String(sqlite3_column_name(vm, i)), AType, DataSize);
//Set the pchar2sql function
if AType in [ftString, ftMemo] then
FGetSqlStr[i] := @Char2SQLStr
else
FGetSqlStr[i] := @Num2SQLStr;
{$ifdef DEBUG_SQLITEDS}
WriteLn(' Field[', i, '] Name: ', sqlite3_column_name(vm, i));
WriteLn(' Field[', i, '] Type: ', sqlite3_column_decltype(vm, i));
{$endif}
end;
sqlite3_finalize(vm);}
end;
function TSqliteJNIDataset.GetRowsAffected: Integer;
begin
DebugLn('[TSqliteJNIDataset.GetRowsAffected]');
//f/Result := sqlite3_changes(FSqliteHandle);
end;
procedure TSqliteJNIDataset.ExecuteDirect(const ASQL: String);
var
vm: Pointer;
begin
DebugLn('[TSqliteJNIDataset.ExecuteDirect]');
{FReturnCode := sqlite3_prepare(FSqliteHandle, Pchar(ASQL), -1, @vm, nil);
if FReturnCode <> SQLITE_OK then
DatabaseError(ReturnString, Self);
FReturnCode := sqlite3_step(vm);
sqlite3_finalize(vm);}
end;
procedure TSqliteJNIDataset.FindJavaClassesAndMethods;
begin
FSQLiteDatabaseClass := javaEnvRef^^.FindClass(javaEnvRef, 'android/database/sqlite/SQLiteDatabase');
FSQLiteClosableClass := javaEnvRef^^.FindClass(javaEnvRef, 'android/database/sqlite/SQLiteClosable');
// Methods from SqliteDatabase
FSqliteDatabase_ExecSQLMethod := javaEnvRef^^.GetMethodID(javaEnvRef, FSQLiteDatabaseClass, 'execSQL',
'(Ljava/lang/String;)V');
FSqliteDatabase_openOrCreateDatabase := javaEnvRef^^.GetStaticMethodID(javaEnvRef, FSQLiteDatabaseClass, 'openOrCreateDatabase',
'(Ljava/lang/String;Landroid/database/sqlite/SQLiteDatabase/CursorFactory;)Landroid/database/sqlite/SQLiteDatabase;');
FSqliteDatabase_getVersion := javaEnvRef^^.GetMethodID(javaEnvRef, FSQLiteDatabaseClass, 'getVersion',
'()I');
// Methods from SqliteClosable
FSqliteClosable_Close := javaEnvRef^^.GetMethodID(javaEnvRef, FSQLiteClosableClass, 'close',
'()V');
end;
procedure TSqliteJNIDataset.BuildLinkedList;
var
TempItem: PDataRecord;
vm: Pointer;
Counter, ColumnCount: Integer;
begin
DebugLn('[TSqliteJNIDataset.BuildLinkedList]');
{ //Get AutoInc Field initial value
if FAutoIncFieldNo <> -1 then
sqlite3_exec(FSqliteHandle, PChar('Select Max(' + FieldDefs[FAutoIncFieldNo].Name +
') from ' + FTableName), @GetAutoIncValue, @FNextAutoInc, nil);
FReturnCode := sqlite3_prepare(FSqliteHandle, PChar(FEffectiveSQL), -1, @vm, nil);
if FReturnCode <> SQLITE_OK then
DatabaseError(ReturnString, Self);
FDataAllocated := True;
TempItem := FBeginItem;
FRecordCount := 0;
ColumnCount := sqlite3_column_count(vm);
FRowCount := ColumnCount;
//add extra rows for calculated fields
if FCalcFieldList <> nil then
Inc(FRowCount, FCalcFieldList.Count);
FRowBufferSize := (SizeOf(PPChar) * FRowCount);
FReturnCode := sqlite3_step(vm);
while FReturnCode = SQLITE_ROW do
begin
Inc(FRecordCount);
New(TempItem^.Next);
TempItem^.Next^.Previous := TempItem;
TempItem := TempItem^.Next;
GetMem(TempItem^.Row, FRowBufferSize);
for Counter := 0 to ColumnCount - 1 do
TempItem^.Row[Counter] := StrNew(sqlite3_column_text(vm, Counter));
//initialize calculated fields with nil
for Counter := ColumnCount to FRowCount - 1 do
TempItem^.Row[Counter] := nil;
FReturnCode := sqlite3_step(vm);
end;
sqlite3_finalize(vm);
// Attach EndItem
TempItem^.Next := FEndItem;
FEndItem^.Previous := TempItem;
// Alloc temporary item used in append/insert
GetMem(FCacheItem^.Row, FRowBufferSize);
for Counter := 0 to FRowCount - 1 do
FCacheItem^.Row[Counter] := nil;
// Fill FBeginItem.Row with nil -> necessary for avoid exceptions in empty datasets
GetMem(FBeginItem^.Row, FRowBufferSize);
//Todo: see if is better to nullif using FillDWord
for Counter := 0 to FRowCount - 1 do
FBeginItem^.Row[Counter] := nil;}
end;
function TSqliteJNIDataset.GetLastInsertRowId: Int64;
begin
DebugLn('[TSqliteJNIDataset.GetLastInsertRowId]');
//f/Result := sqlite3_last_insert_rowid(FSqliteHandle);
end;
function TSqliteJNIDataset.ReturnString: String;
begin
DebugLn('[TSqliteJNIDataset.ReturnString]');
//f/Result := SqliteCode2Str(FReturnCode) + ' - ' + sqlite3_errmsg(FSqliteHandle);
end;
class function TSqliteJNIDataset.SqliteVersion: String;
var
intVersion: JInt;
begin
DebugLn('[TSqliteJNIDataset.SqliteVersion]');
// public int getVersion ()
//intVersion := javaEnvRef^^.CallIntMethod(javaEnvRef, AndroidDB, FSqliteClosable_getVersion);
Result := '3.4'; // IntToStr(intVersion); cant access AndroidDB in class method
DebugLn('[TSqliteJNIDataset.SqliteVersion] Result='+Result);
end;
function TSqliteJNIDataset.QuickQuery(const ASQL: String; const AStrList: TStrings; FillObjects:Boolean): String;
var
vm: Pointer;
{ procedure FillStrings;
begin
while FReturnCode = SQLITE_ROW do
begin
AStrList.Add(String(sqlite3_column_text(vm,0)));
FReturnCode := sqlite3_step(vm);
end;
end;
procedure FillStringsAndObjects;
begin
while FReturnCode = SQLITE_ROW do
begin
AStrList.AddObject(String(sqlite3_column_text(vm, 0)),
TObject(PtrInt(sqlite3_column_int(vm, 1))));
FReturnCode := sqlite3_step(vm);
end;
end; }
begin
DebugLn('[TSqliteJNIDataset.QuickQuery]');
{ if FSqliteHandle = nil then
GetSqliteHandle;
Result := '';
FReturnCode := sqlite3_prepare(FSqliteHandle,Pchar(ASQL), -1, @vm, nil);
if FReturnCode <> SQLITE_OK then
DatabaseError(ReturnString, Self);
FReturnCode := sqlite3_step(vm);
if (FReturnCode = SQLITE_ROW) and (sqlite3_column_count(vm) > 0) then
begin
Result := String(sqlite3_column_text(vm, 0));
if AStrList <> nil then
begin
if FillObjects and (sqlite3_column_count(vm) > 1) then
FillStringsAndObjects
else
FillStrings;
end;
end;
sqlite3_finalize(vm); }
end;
end.