mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-15 18:39:09 +02:00
LCL-CustomDrawn-Android: Adds code to store the Android API level at startup and advances the SQLite code
git-svn-id: trunk@39429 -
This commit is contained in:
parent
37d52863c7
commit
a322953370
@ -46,13 +46,14 @@ type
|
|||||||
|
|
||||||
TSqliteJNIDataset = class(TCustomSqliteDataset)
|
TSqliteJNIDataset = class(TCustomSqliteDataset)
|
||||||
private
|
private
|
||||||
|
FLastInsertRowId: Int64;
|
||||||
// Java Classes
|
// Java Classes
|
||||||
FSqliteClosableClass, FSQLiteDatabaseClass, FSQLiteCursor: JClass;
|
FSqliteClosableClass, FSQLiteDatabaseClass, FDBCursorClass: JClass;
|
||||||
// Java Methods
|
// Java Methods
|
||||||
FSqliteClosable_releaseReference: JMethodID;
|
FSqliteClosable_releaseReference: JMethodID;
|
||||||
FSqliteDatabase_ExecSQLMethod, FSqliteDatabase_openOrCreateDatabase,
|
FSqliteDatabase_ExecSQLMethod, FSqliteDatabase_openOrCreateDatabase,
|
||||||
FSqliteDatabase_getVersion, FSqliteDatabase_query: JMethodID;
|
FSqliteDatabase_getVersion, FSqliteDatabase_query: JMethodID;
|
||||||
FSqliteCursor_getColumnCount: JMethodID;
|
FDBCursor_getColumnCount, FDBCursor_getColumnName, FDBCursor_getType: JMethodID;
|
||||||
// Java Objects
|
// Java Objects
|
||||||
AndroidDB: jobject; // SQLiteDatabase
|
AndroidDB: jobject; // SQLiteDatabase
|
||||||
procedure FindJavaClassesAndMethods;
|
procedure FindJavaClassesAndMethods;
|
||||||
@ -76,6 +77,16 @@ implementation
|
|||||||
uses
|
uses
|
||||||
db, strutils, lclproc;
|
db, strutils, lclproc;
|
||||||
|
|
||||||
|
const
|
||||||
|
//
|
||||||
|
// from android.database.Cursor
|
||||||
|
//
|
||||||
|
FIELD_TYPE_BLOB = 4; // Added in API level 11
|
||||||
|
FIELD_TYPE_FLOAT = 2; // Added in API level 11
|
||||||
|
FIELD_TYPE_INTEGER = 1;// Added in API level 11
|
||||||
|
FIELD_TYPE_NULL = 0; // Added in API level 11
|
||||||
|
FIELD_TYPE_STRING = 3; // Added in API level 11
|
||||||
|
|
||||||
{
|
{
|
||||||
Java code example
|
Java code example
|
||||||
Docs: http://developer.android.com/reference/android/database/sqlite/SQLiteDatabase.html
|
Docs: http://developer.android.com/reference/android/database/sqlite/SQLiteDatabase.html
|
||||||
@ -199,9 +210,12 @@ end;
|
|||||||
procedure TSqliteJNIDataset.RetrieveFieldDefs;
|
procedure TSqliteJNIDataset.RetrieveFieldDefs;
|
||||||
var
|
var
|
||||||
vm: Pointer;
|
vm: Pointer;
|
||||||
ColumnStr: String;
|
ColumnName: string;
|
||||||
i, ColumnCount, DataSize: Integer;
|
i, ColumnCount, DataSize: Integer;
|
||||||
|
lColumnType: JInt;
|
||||||
|
lJavaString: JString;
|
||||||
AType: TFieldType;
|
AType: TFieldType;
|
||||||
|
lNativeString: PChar;
|
||||||
//
|
//
|
||||||
dbCursor: JObject;
|
dbCursor: JObject;
|
||||||
lParams: array[0..7] of JValue;
|
lParams: array[0..7] of JValue;
|
||||||
@ -228,99 +242,97 @@ begin
|
|||||||
Exit;
|
Exit;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// int num = c.getColumnCount();
|
|
||||||
// for (int i = 0; i < num; ++i)
|
|
||||||
{
|
|
||||||
String colname = c.getColumnName(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//FReturnCode := sqlite3_prepare(FSqliteHandle, PChar(FEffectiveSQL), -1, @vm, nil);
|
//FReturnCode := sqlite3_prepare(FSqliteHandle, PChar(FEffectiveSQL), -1, @vm, nil);
|
||||||
//if FReturnCode <> SQLITE_OK then
|
//if FReturnCode <> SQLITE_OK then
|
||||||
// DatabaseError(ReturnString, Self);
|
// DatabaseError(ReturnString, Self);
|
||||||
//sqlite3_step(vm);
|
//sqlite3_step(vm);
|
||||||
//ColumnCount := sqlite3_column_count(vm);
|
//ColumnCount := sqlite3_column_count(vm);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Obtain the number of columns
|
||||||
|
//
|
||||||
|
|
||||||
|
// abstract String getColumnName(int columnIndex)
|
||||||
|
// int ColumnCount = c.getColumnCount();
|
||||||
|
ColumnCount := javaEnvRef^^.CallIntMethod(javaEnvRef, AndroidDB, FDBCursor_getColumnCount);
|
||||||
//Prepare the array of pchar2sql functions
|
//Prepare the array of pchar2sql functions
|
||||||
{ SetLength(FGetSqlStr, ColumnCount);
|
SetLength(FGetSqlStr, ColumnCount);
|
||||||
for i := 0 to ColumnCount - 1 do
|
for i := 0 to ColumnCount - 1 do
|
||||||
begin
|
begin
|
||||||
|
//
|
||||||
|
// First get the column name
|
||||||
|
//
|
||||||
|
// abstract String getColumnName(int columnIndex)
|
||||||
|
lParams[0].i := i;
|
||||||
|
lJavaString := javaEnvRef^^.CallObjectMethodA(javaEnvRef, AndroidDB, FDBCursor_getColumnName, @lParams[0]);
|
||||||
|
lNativeString := javaEnvRef^^.GetStringUTFChars(javaEnvRef, lJavaString, nil);
|
||||||
|
ColumnName := lNativeString;
|
||||||
|
javaEnvRef^^.ReleaseStringUTFChars(javaEnvRef, lJavaString, lNativeString);
|
||||||
|
javaEnvRef^^.DeleteLocalRef(javaEnvRef, lJavaString);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Now obtain the data size and type
|
||||||
|
//
|
||||||
DataSize := 0;
|
DataSize := 0;
|
||||||
ColumnStr := UpperCase(String(sqlite3_column_decltype(vm, i)));
|
|
||||||
if (ColumnStr = 'INTEGER') or (ColumnStr = 'INT') then
|
// Before Android 3.0 there is no way to know the type of the field, so just suppose it is string
|
||||||
begin
|
if android_os_Build_VERSION_SDK_INT < 11 then
|
||||||
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
|
begin
|
||||||
AType := ftString;
|
AType := ftString;
|
||||||
DataSize := StrToIntDef(Trim(ExtractDelimited(2, ColumnStr, ['(', ')'])), DefaultStringSize);
|
DataSize := DefaultStringSize;
|
||||||
end else if Pos('BOOL', ColumnStr) = 1 then
|
end
|
||||||
|
else
|
||||||
|
// In Android 3.0 we can use Cursor.getType
|
||||||
begin
|
begin
|
||||||
AType := ftBoolean;
|
// public abstract int getType (int columnIndex) // Added in API level 11
|
||||||
end else if Pos('AUTOINC', ColumnStr) = 1 then
|
lParams[0].i := i;
|
||||||
begin
|
lColumnType := javaEnvRef^^.CallIntMethodA(javaEnvRef, AndroidDB, FDBCursor_getType, @lParams[0]);
|
||||||
AType := ftAutoInc;
|
|
||||||
if FAutoIncFieldNo = -1 then
|
case lColumnType of
|
||||||
FAutoIncFieldNo := i;
|
FIELD_TYPE_BLOB:
|
||||||
end else if (Pos('FLOAT', ColumnStr) = 1) or (Pos('NUMERIC', ColumnStr) = 1) then
|
begin
|
||||||
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;
|
AType := ftString;
|
||||||
DataSize := DefaultStringSize;
|
DataSize := DefaultStringSize;
|
||||||
end;
|
end;
|
||||||
|
FIELD_TYPE_FLOAT:
|
||||||
|
begin
|
||||||
|
AType := ftFloat;
|
||||||
|
end;
|
||||||
|
FIELD_TYPE_INTEGER:
|
||||||
|
begin
|
||||||
|
{if AutoIncrementKey and (UpperCase(String(sqlite3_column_name(vm, i))) = UpperCase(PrimaryKey)) then
|
||||||
|
begin
|
||||||
|
AType := ftAutoInc;
|
||||||
|
FAutoIncFieldNo := i;
|
||||||
|
end
|
||||||
|
else}
|
||||||
|
AType := ftInteger;
|
||||||
|
end;
|
||||||
|
FIELD_TYPE_NULL:
|
||||||
|
begin
|
||||||
|
AType := ftString;
|
||||||
|
DataSize := DefaultStringSize;
|
||||||
|
end;
|
||||||
|
FIELD_TYPE_STRING:
|
||||||
|
begin
|
||||||
|
AType := ftString;
|
||||||
|
DataSize := DefaultStringSize;
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
end else
|
|
||||||
begin
|
|
||||||
AType := ftString;
|
|
||||||
DataSize := DefaultStringSize;
|
|
||||||
end;
|
end;
|
||||||
FieldDefs.Add(String(sqlite3_column_name(vm, i)), AType, DataSize);
|
|
||||||
|
FieldDefs.Add(ColumnName, AType, DataSize);
|
||||||
//Set the pchar2sql function
|
//Set the pchar2sql function
|
||||||
if AType in [ftString, ftMemo] then
|
if AType in [ftString, ftMemo] then
|
||||||
FGetSqlStr[i] := @Char2SQLStr
|
FGetSqlStr[i] := @Char2SQLStr
|
||||||
else
|
else
|
||||||
FGetSqlStr[i] := @Num2SQLStr;
|
FGetSqlStr[i] := @Num2SQLStr;
|
||||||
{$ifdef DEBUG_SQLITEDS}
|
{$ifdef DEBUG_SQLITEDS}
|
||||||
WriteLn(' Field[', i, '] Name: ', sqlite3_column_name(vm, i));
|
DebugLn(' Field[', i, '] Name: ', sqlite3_column_name(vm, i));
|
||||||
WriteLn(' Field[', i, '] Type: ', sqlite3_column_decltype(vm, i));
|
DebugLn(' Field[', i, '] Type: ', sqlite3_column_decltype(vm, i));
|
||||||
{$endif}
|
{$endif}
|
||||||
end;
|
end;
|
||||||
sqlite3_finalize(vm);}
|
//sqlite3_finalize(vm);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TSqliteJNIDataset.GetRowsAffected: Integer;
|
function TSqliteJNIDataset.GetRowsAffected: Integer;
|
||||||
@ -345,7 +357,7 @@ procedure TSqliteJNIDataset.FindJavaClassesAndMethods;
|
|||||||
begin
|
begin
|
||||||
FSQLiteDatabaseClass := javaEnvRef^^.FindClass(javaEnvRef, 'android/database/sqlite/SQLiteDatabase');
|
FSQLiteDatabaseClass := javaEnvRef^^.FindClass(javaEnvRef, 'android/database/sqlite/SQLiteDatabase');
|
||||||
FSQLiteClosableClass := javaEnvRef^^.FindClass(javaEnvRef, 'android/database/sqlite/SQLiteClosable');
|
FSQLiteClosableClass := javaEnvRef^^.FindClass(javaEnvRef, 'android/database/sqlite/SQLiteClosable');
|
||||||
FSQLiteCursor := javaEnvRef^^.FindClass(javaEnvRef, 'android/database/Cursor');
|
FDBCursorClass := javaEnvRef^^.FindClass(javaEnvRef, 'android/database/Cursor');
|
||||||
|
|
||||||
//
|
//
|
||||||
// Methods from SqliteDatabase
|
// Methods from SqliteDatabase
|
||||||
@ -361,10 +373,24 @@ begin
|
|||||||
FSqliteDatabase_query := javaEnvRef^^.GetMethodID(javaEnvRef, FSQLiteDatabaseClass, 'query',
|
FSqliteDatabase_query := javaEnvRef^^.GetMethodID(javaEnvRef, FSQLiteDatabaseClass, 'query',
|
||||||
'(Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Landroid/database/Cursor;');
|
'(Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Landroid/database/Cursor;');
|
||||||
//
|
//
|
||||||
// Methods from FSQLiteCursor
|
// Methods from FDBClosable
|
||||||
//
|
//
|
||||||
FSqliteCursor_getColumnCount := javaEnvRef^^.GetMethodID(javaEnvRef, FSQLiteCursor, 'getColumnCount',
|
FSqliteClosable_releaseReference := javaEnvRef^^.GetMethodID(javaEnvRef, FSQLiteClosableClass, 'releaseReference',
|
||||||
|
'()V');
|
||||||
|
//
|
||||||
|
// Methods from FDBCursor
|
||||||
|
//
|
||||||
|
FDBCursor_getColumnCount := javaEnvRef^^.GetMethodID(javaEnvRef, FDBCursorClass, 'getColumnCount',
|
||||||
'()I');
|
'()I');
|
||||||
|
// abstract String getColumnName(int columnIndex)
|
||||||
|
FDBCursor_getColumnName := javaEnvRef^^.GetMethodID(javaEnvRef, FDBCursorClass, 'getColumnName',
|
||||||
|
'(I)Ljava/lang/String;');
|
||||||
|
// public abstract int getType (int columnIndex) // Added in API level 11
|
||||||
|
if android_os_Build_VERSION_SDK_INT >= 11 then
|
||||||
|
begin
|
||||||
|
FDBCursor_getType := javaEnvRef^^.GetMethodID(javaEnvRef, FDBCursorClass, 'getType',
|
||||||
|
'(I)I');
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TSqliteJNIDataset.BuildLinkedList;
|
procedure TSqliteJNIDataset.BuildLinkedList;
|
||||||
@ -427,7 +453,8 @@ end;
|
|||||||
|
|
||||||
function TSqliteJNIDataset.GetLastInsertRowId: Int64;
|
function TSqliteJNIDataset.GetLastInsertRowId: Int64;
|
||||||
begin
|
begin
|
||||||
DebugLn('[TSqliteJNIDataset.GetLastInsertRowId]');
|
Result := FLastInsertRowId;
|
||||||
|
DebugLn('[TSqliteJNIDataset.GetLastInsertRowId] Result='+IntToStr(Result));
|
||||||
//f/Result := sqlite3_last_insert_rowid(FSqliteHandle);
|
//f/Result := sqlite3_last_insert_rowid(FSqliteHandle);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
@ -370,6 +370,9 @@ var
|
|||||||
javaActivityClass: JClass = nil;
|
javaActivityClass: JClass = nil;
|
||||||
javaActivityObject: jobject = nil;
|
javaActivityObject: jobject = nil;
|
||||||
|
|
||||||
|
// The SDK Version
|
||||||
|
android_os_Build_VERSION_SDK_INT: jint;
|
||||||
|
|
||||||
// Other classes and objects
|
// Other classes and objects
|
||||||
javaAndroidAppActivityClass: JClass = nil;
|
javaAndroidAppActivityClass: JClass = nil;
|
||||||
javaJavaLangSystemClass: JClass = nil;
|
javaJavaLangSystemClass: JClass = nil;
|
||||||
@ -377,7 +380,10 @@ var
|
|||||||
javaAndroidOSVibratorClass: JClass = nil;
|
javaAndroidOSVibratorClass: JClass = nil;
|
||||||
javaAndroidContentContextClass: JClass = nil;
|
javaAndroidContentContextClass: JClass = nil;
|
||||||
javaJavaLangStringClass: JClass = nil;
|
javaJavaLangStringClass: JClass = nil;
|
||||||
|
javaAndroidOSBuildVERSIONClass: JClass = nil;
|
||||||
|
|
||||||
|
// Other fields
|
||||||
|
javaField_VERSION_SDK_INT: JFieldID = nil;
|
||||||
// Fields of our Activity
|
// Fields of our Activity
|
||||||
// Strings
|
// Strings
|
||||||
javaField_lcltext: JfieldID=nil;
|
javaField_lcltext: JfieldID=nil;
|
||||||
|
@ -535,6 +535,7 @@ begin
|
|||||||
javaAndroidOSVibratorClass := javaEnvRef^^.FindClass(javaEnvRef,'android/os/Vibrator');
|
javaAndroidOSVibratorClass := javaEnvRef^^.FindClass(javaEnvRef,'android/os/Vibrator');
|
||||||
javaAndroidContentContextClass := javaEnvRef^^.FindClass(javaEnvRef,'android/content/Context');
|
javaAndroidContentContextClass := javaEnvRef^^.FindClass(javaEnvRef,'android/content/Context');
|
||||||
javaJavaLangStringClass := javaEnvRef^^.FindClass(javaEnvRef,'java/lang/String');
|
javaJavaLangStringClass := javaEnvRef^^.FindClass(javaEnvRef,'java/lang/String');
|
||||||
|
javaAndroidOSBuildVERSIONClass := javaEnvRef^^.FindClass(javaEnvRef, 'android/os/Build$VERSION');
|
||||||
|
|
||||||
// Register Pascal exported calls
|
// Register Pascal exported calls
|
||||||
if javaEnvRef^^.RegisterNatives(javaEnvRef, javaActivityClass, @NativeMethods[0],length(NativeMethods))<0 then
|
if javaEnvRef^^.RegisterNatives(javaEnvRef, javaActivityClass, @NativeMethods[0],length(NativeMethods))<0 then
|
||||||
@ -606,6 +607,10 @@ begin
|
|||||||
// Generic methods from Context
|
// Generic methods from Context
|
||||||
javaMethod_getSystemService := javaEnvRef^^.GetMethodID(javaEnvRef, javaAndroidContentContextClass, 'getSystemService', '(Ljava/lang/String;)Ljava/lang/Object;');
|
javaMethod_getSystemService := javaEnvRef^^.GetMethodID(javaEnvRef, javaAndroidContentContextClass, 'getSystemService', '(Ljava/lang/String;)Ljava/lang/Object;');
|
||||||
|
|
||||||
|
// Read the SDK Version and store it
|
||||||
|
javaField_VERSION_SDK_INT := javaEnvRef^^.GetStaticFieldID(javaEnvRef, javaAndroidOSBuildVERSIONClass, 'SDK_INT', 'I');
|
||||||
|
android_os_Build_VERSION_SDK_INT := javaEnvRef^^.GetStaticIntField(javaEnvRef, javaAndroidOSBuildVERSIONClass, javaField_VERSION_SDK_INT);
|
||||||
|
|
||||||
__android_log_write(ANDROID_LOG_INFO, 'lclapp', 'JNI_OnLoad finished');
|
__android_log_write(ANDROID_LOG_INFO, 'lclapp', 'JNI_OnLoad finished');
|
||||||
result:=JNI_VERSION_1_4;// 1_6 is another option
|
result:=JNI_VERSION_1_4;// 1_6 is another option
|
||||||
end;
|
end;
|
||||||
|
Loading…
Reference in New Issue
Block a user