Category: Firemonkey

How to reference NFCNDEFReaderSession from IOSapi.CoreNFC in Delphi FMX App

I try to include some NFC reading functionality in my Delphi IOS 64bit App. (RAD Studio 10.3.2). But I cannot find the right way to reference NFCNDEFReaderSession. All results in the message ObjectiveC class NFCNDEFReaderSession could not be found. uses System.SysUtils, Macapi.ObjectiveC, iOSapi.Foundation, iOSapi.CoreNFC, FMX.Helpers.iOS; type //..... //from IOapi.CoreNFC only for information NFCNDEFReaderSessionClass = interface(NFCReaderSessionClass) ['{8F8EFAB7-FEC0-4DC8-ABD2-669A639617E4}'] end; NFCNDEFReaderSession = interface(NFCReaderSession) ['{11F096EA-B10B-4566-909F-5C72A930084A}'] procedure setReadingAvailable(readingAvailable: Boolean); cdecl; function readingAvailable: Boolean; cdecl; function initWithDelegate(delegate: Pointer; queue: dispatch_queue_t; invalidateAfterFirstRead: Boolean): Pointer { instancetype }; cdecl; end; //..... TNFCNDEFReaderSession = class(TOCGenericImport<NFCNDEFReaderSessionClass, NFCNDEFReaderSession>) end; TNFCNDEFReaderSessionDelegate = class(TOCLocal,NFCNDEFReaderSessionDelegate) public procedure readerSessionDidInvalidateWithError(session: NFCNDEFReaderSession; didInvalidateWithError: NSError); cdecl; procedure readerSessionDidDetectNDEFs(session: NFCNDEFReaderSession; didDetectNDEFs: NSArray); cdecl; end; TIOS_NFCUtil = class private sessionDelegate: TNFCNDEFReaderSessionDelegate; session : NFCNDEFReaderSession; public constructor create; end; var IOS_NFCUtil: TIOS_NFCUtil; implementation uses FMX.DialogService; { TIOS_NFCUtil } constructor TIOS_NFCUtil.create; var rsession: NFCReaderSession; begin try sessionDelegate := TNFCNDEFReaderSessionDelegate.Create; // Create OK rsession := TNFCReaderSession.Create; // Session := TNFCNDEFReaderSession.Create; session := TNFCNDEFReaderSession.Wrap(TNFCNDEFReaderSession.Alloc.initWithDelegate(sessionDelegate,nil, false)); except on e: Exception do begin TDialogService.showmessage(e.Message); end; end; end; How to initialize the NFC session? ---> session:=NFCNDEFReaderSession.Wrap(TNFCNDEFReaderSession.Alloc.initWithDelegate(sessionDelegate,nil, false)); Checked out to initialize NFCNDEFReaderSession inside TNFCNDEFReaderSessionDelegate class, but ObjectiveC class is still not found type TNFCNDEFReaderSessionDelegate = class(TOCLocal,NFCNDEFReaderSessionDelegate) private session: NFCNDEFReaderSession; public procedure InitReaderSession; procedure readerSessionDidInvalidateWithError(session: NFCNDEFReaderSession; didInvalidateWithError: NSError); cdecl; procedure readerSessionDidDetectNDEFs(session: NFCNDEFReaderSession; didDetectNDEFs: NSArray); cdecl; end; procedure TNFCNDEFReaderSessionDelegate.InitReaderSession; var step: Integer; begin try step := 0; //session := TNFCNDEFReaderSession.Create; TNFCNDEFReaderSession.Wrap(TNFCNDEFReaderSession.Alloc.initWithDelegate(self,nil,false)); step := 1; (*if assigned(session) then begin step := 2; session.initWithDelegate(self,nil,false); step := 3; session.beginSession; step := 4; end; *) except on e: Exception do begin TDialogService.showmessage(e.Message+ ' ' + step.ToString); end; end; end; MessageBox: ObjectiveC class not found (step 0) also in case of session := TNFCNDEFReaderSession.Create;
Read More

August 2019 RAD Studio Roadmap Udpate

On the Embarcadero developer community site, there is a new blog post by Sarina DuPont covering: August 2019 Delphi Android Beta Plans & August Roadmap Update The blog post has an update to the May 2019 roadmap and it also highlights the plans around a Delphi Android 64-bit Beta that's going to be made available soon to update subscription customers. Read the article linked above for all of the details.
Read More

iOS Notification sound playing in app, although this hasn’t been initiated by me (iOS 12 only)

Ever since updating devices to iOS 12, my Delphi application has started playing sound notifications when a specific operation is done in the application. This has not been coded or configured by me. When using the application in iOS 11 or lower, the sound notification does not play. The project is built and compiled in Delphi 10.3.1. I cannot find any mentions of this phenomena anywhere in the RAD Studio documentation, or online. Disabling notifications for the application in the iOS settings does work, however this solution has its drawbacks obviously. Edit: This is the documentation I have been reading: http://docwiki.embarcadero.com/RADStudio/Rio/en/Mobile_Tutorial:_Using_Notifications_(iOS_and_Android) This operation, when initiated, starts an animation of a spinning wheel, indicating waiting (not TAniIndicator). A TTimer is also started at this point, indicating to the user how long the wait has been. However, I cannot see how the event handler in the timer could make this happen: procedure MainForm.timer_loadingTimer(Sender: TObject); begin tt_loadingText.Tag := tt_loadingText.Tag + 1; tt_loadingText.Text := tt_loadingText.Tag.ToString + ' seconds.'; end; Has anyone ever run into the same issue, and has any idea what could cause it? I suspect there is some configuration somewhere, or maybe it is a side effect hidden deep in my code.
Read More

Prevent firing events while scrolling TVertScrollBox

Normally, while scrolling the contents of a "scroll box", no event functions are fired from the sub-components of a scroll box, e. g. in native apps. But in FireMonkey, if a TVertScrollBox contains sub-elements like TRectangle (which I want to use as menu entries for a custom menu), scrolling the TVertScrollBox on Android with a finger sometimes triggers the event functions (like OnClick) of the sub-elements and this is very confusing for me and our customers - They don't want to tap a specific element while scrolling. In native apps this never happens. I couldn't figure out how to prevent this behaviour. I tried to set the HitTest property to FALSE for all sub-elements in the OnMouseEnter and OnMouseLeave (I also tried other events) with something like this: procedure TframeCornerMenu.VertScrollBox1MouseEnter(Sender: TObject); var list: TRectangle; i: Integer; begin list := FindComponent('rectMenuList') as TRectangle; for i := 0 to list.ChildrenCount - 1 do begin if list.Children[i] is TRectangle then TRectangle(list.Children[i]).HitTest := false; end; end; But this obviously doesn't (and can't) work, because the user taps the sub-elements first which are lying on top of the TVertScrollBox. Is this a bug / not implemented feature in FireMonkey? I appreciate all ideas solving this scrolling problem. If possible, without third-party components. I am using Delphi Community Edition 10.3.2 (26.0.34749.6593).
Read More

How to check a BLE device still connected with Delphi 10.3

I've successfully connected my Delphi(FM) app to a ESP32 device and I can send commands/receive data over BLE (I am showing a message for connection status after connection is successful/unsuccessful). But problem is that, if user close/power off the ESP32 device then mobile app still shows connection established. I've tried both System.Bluetooth.TBluetoothConnectionState and System.Bluetooth.TBluetoothLEManager.ConnectionState with a TTimer but no success. if not (BLEDevice1.ConnectionState = TBluetoothConnectionState.Connected) then begin Showmessge('Connection not established!'); // this type of control doesn't change anything. end;
Read More

Proper way to detect on button click on a Dynamic Listview Appearance

My listview is set to dynamic appearance. It has 2 TListItemTextButtons on it. I want to assign a sort of "OnClick" event to each of those buttons on each items. The thing is Almost every listview items needs a different proc to run on it and I know exactly how to do it. When I normally create a dynamic TButton I can assign a custom proc to it using AnonProc2NotifyEvent from TProc<TObject> to TNotifyEvent. I'm aware of the OnItemClickEx a normal listview has but it seems a little buggy. Example: lets say Listviewitem has a itemindex of 3 and you as a user click on the button in listviewitem 1 then the button from listviewitem 3 will activate. Embarcadero Docs says that there's a OnClick event however I cannot find one: http://docwiki.appmethod.com/appmethod/1.15/libraries/en/FMX.ListView.Types.TListItemTextButton_Events How can I go about assigning a OnClick for a TListItemTextButton? Example of what I want to do: LItem.Objects.FindObjectT<TListItemText>('Username').Text := 'Some username'; LItem.Objects.FindObjectT<TListItemText>('Info').Text := 'Some extra info'; LItem.Objects.FindObjectT<TListItemTextButton>('Kick').OnClick := AnonProc2NotifyEvent(lvPlayers, procedure(Sender: TObject) begin SendRconCommand('removeconnection ' + jplayers['userid'].AsString); end); However this provides a Undeclared Identifier for OnClick.
Read More

How to use curl for Dropbox token in Firemonkey

I’m trying to get Dropbox token base on Dropbox documentation. For that I have to use (from Dropbox documentation): https://www.dropbox.com/developers/documentation/http/documentation#oauth2-token URL: https://api.dropboxapi.com/oauth2/token METHOD: POST EXAMPLE: curl https://api.dropbox.com/oauth2/token \ -d code=<AUTHORIZATION_CODE> \ -d grant_type=authorization_code \ -d redirect_uri=<REDIRECT_URI> \ -u <APP_KEY>:<APP_SECRET> But I don't know how to do that in Firemonkey. I was trying to do something like that but without success. My code: HTTP := TIdHTTP.Create(nil); try HTTP.HandleRedirects := True; HTTP.ConnectTimeout := FHTTPTimeout; HTTP.Request.BasicAuthentication := False; HTTP.IOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(HTTP); HTTP.Request.Accept := 'application/x-www-form-urlencoded'; HTTP.Request.ContentType := 'application/json'; sTemp:= '{ "code"="<' + Settings.SynchroDropBoxCode + '>" ' + keyCrLf + ' "grant_type"="authorization_code" ' + keyCrLf + ' "redirect_uri"="<http://127.0.0.1:8888/>" ' + keyCrLf + ' "<' + cloudDropBoxMobileAppKey + '>":"<'+cloudDropBoxMobileAppKeySecret+'>" }'; DataToSend := TStringStream.Create(sTemp, TEncoding.UTF8, True); try sHTTPResponse := HTTP.Post('https://api.dropbox.com/oauth2/token', DataToSend); finally DataToSend.Free; end; finally HTTP.Free; end;
Read More

Getting parameters from IdHTTPServer – Firemonkey

I’m trying to get Dropbox token from call-back parameters but the parameters are always empty. Here is my code: sURL := https://www.dropbox.com/oauth2/authorize' + '?response_type=token' + '&client_id=' + MyAppID + '&redirect_uri=http://127.0.0.1:8888/'; ShellExecute(0, 'OPEN', PChar(sURL), '', '', SW_SHOWNORMAL); Next I have IdHTTPServer set to listen http://127.0.0.1:8888/ address. On executing the browser with Dropbox log-in popup. When I made log-in the redirection is made and the “IdHTTPServerCommandGet” events is called. So far so good. In the browser I can see the next URL: http://127.0.0.1:8888/#access_token=123&token_type=bearer&uid=1234&account_id=dbid%1234 But in “IdHTTPServerCommandGet” events the parameters are always empty: ARequestInfo.UnparsedParams; // Empty ARequestInfo. QueryParams; // Empty if ARequestInfo.Params.Count > 0 then // Empty sToken := ARequestInfo.Params[0]; And here is my question. How can I get the whole URL with parameters from IdHTTPServer?
Read More

Pick columns from csv (FMX, C++)

I am reading one column of data out of a big CSV file (column 3). I want to know if there is a more efficient way of doing this. Right now i read each entire row, and then pick out my column. String S; TStringList *List = new TStringList; List->LoadFromFile(myCSV); // load the CSV file std::auto_ptr<TStringList>pListA(new TStringList); for (int i = 0; i < 400; i++) { // for testing just getting first 400 rows. pListA->Text = StringReplace(List[0].Strings[i], ",", "\r\n", TReplaceFlags() << rfReplaceAll); S = pListA->Strings[3]; // do something with this value from column 3 } This code works fine, but it has to read the entire row of CSV data just to let me get that one column. Below is sample of the first 2 rows from the CSV data: 1,0,-6856,12830,8458,-16666,98717,-10718,-80874,49999,-99998,98569,99998,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,1,0,1,0,1,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 2,8948,-6856,12830,8458,-16666,39641,63125,-99973,99998,-99998,39385,99998,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,1,0,1,0,1,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 UPDATE: Based on Remy's code I ended up with this below. TStreamReader* Reader; Reader = new TStreamReader(myCSV); while (!Reader->EndOfStream) { String S = Reader->ReadLine(); int start = PosEx(_D(","), S, 1); start = PosEx(_D(","), S, start+1) + 1; int end = PosEx(_D(","), S, start); S = S.SubString1(start, end-start); // use S } Reader->Close(); delete Reader->BaseStream; delete Reader;
Read More

Is there a way to write in an locale database?

i'm learning to use firemonkey, and i made an app that i'm using on my phone (it works like a reminder if u want) so basically there's a database file (SQLite) in my phone's internal storage, and in the form i put a TMemo + FDConnection + FDPhysSQLiteDriverLink so the app can read the database and display it on the TMemo, now i did put a TEdit and i added a button i want what i write on the TEdit to be added to the database. i'm new to SQL delphi and stack overflow in general. thanks PS: i'm trying to do it without using livebindings. var query: TFDQuery; begin query := TFDQuery.Create(nil); try // Define the SQL Query query.Connection := FDConnection1; query.SQL.Text := 'SELECT * FROM Employee'; query.Open(); outputMemo.Text := ''; // Add the field names from the table. outputMemo.Lines.Add(String.Format('|%8s|%-25s|%-25s|', [' ID ', ' NAME >', ' DEPARTMENT '])); // Add one line to the memo for each record in the table. while not query.Eof do begin outputMemo.Lines.Add(String.Format('|%8d|%-25s|%-25s|', [query.FieldByName('ID').AsInteger, >query.FieldByName('Name').AsString, query.FieldByName('Department').AsString])); query.Next; end; finally query.Close; query.DisposeOf; end; end; this is the code to display the database, i want to know if there's a way to write on the memo or a TEdit and press a button to change back the database, i'm wondering if it works both ways.
Read More

Delphi FMX dcpcrypt wrong result on macOS 64-bit

I am using Delphi 10.3.2 I am trying to use the DCPCrypt units with the firemonkey framework to encrypt a string. It works 100% on Win32, Win64 and macOS 32 targets, the result is always the same. But when I compile for macOS 64, the result is different. This is the code used: function EncodeAES(code:ansistring; key:ansistring):string; var s,u:ansistring; enc: TEncoding; k,iv, Data, Crypt: TBytes; Cipher: TDCP_rijndael; begin u:=''; enc:=TEncoding.ANSI; Data := enc.GetBytes(code); // VMpuXJGbUNOv k:=enc.GetBytes(key); // kj3214ed)k32nre2 iv:=enc.GetBytes(u); Cipher:=TDCP_rijndael.Create(nil); Cipher.Init(K[0], 128, @iv[0]); Crypt:=Copy(Data, 0, Length(Data)); BytePadding(Crypt, Cipher.BlockSize, pmPKCS7); Cipher.EncryptECB(Crypt[0], Crypt[0]); Cipher.Free; s:=tencoding.ANSI.GetString(crypt); result:=StringToHex(s); end; and this is the BytePadding function: procedure BytePadding(var Data: TBytes; BlockSize: integer; PaddingMode: TPaddingMode); var I, DataBlocks, DataLength, PaddingStart, PaddingCount: integer; begin BlockSize := BlockSize div 8; if PaddingMode in [pmZeroPadding, pmRandomPadding] then if Length(Data) mod BlockSize = 0 then Exit; DataBlocks := (Length(Data) div BlockSize) + 1; DataLength := DataBlocks * BlockSize; PaddingCount := DataLength - Length(Data); if PaddingMode in [pmANSIX923, pmISO10126, pmPKCS7] then if PaddingCount > $FF then Exit; PaddingStart := Length(Data); SetLength(Data, DataLength); case PaddingMode of pmZeroPadding, pmANSIX923, pmISO7816: // fill with $00 bytes FillChar(Data[PaddingStart], PaddingCount, 0); pmPKCS7: // fill with PaddingCount bytes FillChar(Data[PaddingStart], PaddingCount, PaddingCount); pmRandomPadding, pmISO10126: // fill with random bytes for I := PaddingStart to DataLength-1 do Data[I] := Random($FF); end; case PaddingMode of pmANSIX923, pmISO10126: Data[DataLength-1] := PaddingCount; // set end-marker with number of bytes added pmISO7816: Data[PaddingStart] := $80; // set fixed end-markder $80 end; end; I call the function like: procedure TForm1.BtnClick(Sender: TObject); var s:string; begin s:=EncodeAES('VMpuXJGbUNOv','kj3214ed)k32nre2'); end; Result with Win32/Win64/macOS 32 (correct): E32A9DE47CC60BDB70CA27885128D17A Result with macOS 64 (wrong): CF622155545E485AC3A083E8A0478493 What am I doing wrong?
Read More