Jump to content

Yaron

Members
  • Content Count

    286
  • Joined

  • Last visited

  • Days Won

    2

Everything posted by Yaron

  1. I prepared to post a question on how I can do this, but I actually reached a solution on my own while contemplating on how to best phrase the question and code. Since I searched and couldn't find good documentation on how to do this, I decided to post my solution here: Imagine a table with columns: NAME , TAGS , etc ... The TAGS column contains a string with multiple unique identifiers, for example "tag0001|tag0002|tag0003|tag0004". I'm only getting rows with a TAGS column that contains a sub-string I'm looking for (a specific tag) : sTAGUID := 'tag0002'; dbQuery.SQL.Text := 'SELECT * FROM CARDS_TABLE WHERE (POSITION(:taguid,TAGS) > 0) ORDER BY LOWER(NAME) ASC;'; Try dbQuery.Prepare; dbQuery.ParamByName('taguid').AsString := sTAGUID; dbQuery.Open; If dbQuery.RecordCount > 0 then While dbQuery.Eof = False do Begin New(nEntry); ExtractCardQuery(dbQuery,nEntry^); cardList.Add(nEntry); dbQuery.Next; End; finally dbQuery.free end;
  2. I would like to integrate Ad support for my Delphi 7 desktop application (I also have Delphi 10.3.3 which I could possibly use to create a DLL which would integrate into the D7 app). Has anyone here ever create a Delphi desktop app that's supported by advertising? This model is very prevalent in the mobile world, but on the desktop, I haven't found a lot of information. I could easily integrate google ads, but I believe they do not allow ads within desktop applications. Microsoft seems to allow Ads (https://developer.microsoft.com/en-us/store/monetize/ads-in-apps), but the API is designed for UWP apps (am I mistaken?) and I'm not sure how to go about the integration process. Do you suggest other Ad networks that would integrate nicely with Delphi?
  3. For some reason, even when setting the TListView's control to not show the "Details" section, the text within the control is cut at about 80% of the width. I have "ListView.ItemAppearanceObject.ItemObjects.Detail.Visible = False" and "ListView.ItemAppearanceObject.ItemEditObjects.Detail.Visible = False". And "ListView.ItemAppearance" set to "ListItem" (which adds a ">" at the end of the line for some reason).
  4. On Android, RTL text (e.g. Hebrew) appears in reverse order (letter order is reversed). Using the same code, & input (YouTube DATA API 3) and the text appears correctly in windows. I searched the web and the only reference I was able to find is a post from five years ago that says RTL is not supported and there is no roadmap entry for future support: https://stackoverflow.com/questions/28494354/right-to-left-language-in-delphi-xe7-mobile-android Has anything changed since?
  5. I am sharing a video's URL from YouTube to my Android app. I do this using Android Intents by modifying the "AndroidManifest.template.xml", adding: <intent-filter> <action android:name="android.intent.action.SEND" /> <category android:name="android.intent.category.DEFAULT" /> <data android:mimeType="text/plain" /> </intent-filter> Then in my app's form OnCreate event, I use: if TPlatformServices.Current.SupportsPlatformService(IFMXApplicationEventService, AppEventService) then AppEventService.SetApplicationEventHandler(HandleAppEvent); MainActivity.registerIntentAction(TJIntent.JavaClass.ACTION_SEND); TMessageManager.DefaultManager.SubscribeToMessage(TMessageReceivedNotification, HandleActivityMessage); Then HandleAppEvent looks like this: function TMainForm.HandleAppEvent(AAppEvent: TApplicationEvent; AContext: TObject): Boolean; var StartupIntent: JIntent; begin Result := False; Case AAppEvent of TApplicationEvent.BecameActive: Begin clientAndroidBecameActive := True; If clientAndroidActivated = False then Begin clientAndroidActivated := True; StartupIntent := MainActivity.getIntent; if StartupIntent <> nil then Begin HandleIntentAction(StartupIntent); StartupIntent := nil; End; End; End; end; end; And HandleActivityMessage looks like: procedure TMainForm.HandleActivityMessage(const Sender: TObject; const M: TMessage); begin if M is TMessageReceivedNotification then HandleIntentAction(TMessageReceivedNotification(M).Value); end; And finally, HandleIntentAction: function TMainForm.HandleIntentAction(const Data: JIntent): Boolean; var Extras : JBundle; sURL : String; begin Result := False; if Data <> nil then begin Extras := Data.getExtras; if Extras <> nil then Begin sURL := JStringToString(Extras.getString(TJIntent.JavaClass.EXTRA_TEXT)); // Do something useful with the URL Extras := nil; End end end; My problem is there are occasions after sharing where an intent is duplicated, triggering once on the share and again when opening the app later on. Does anyone have experience with something similar?
  6. There's this article: http://www.fmxexpress.com/leaderboards-and-achievements-with-google-play-game-services-in-delphi-xe5-xe6-xe7-firemonkey-on-android/ It's a bit outdated, but perhaps it would help.
  7. This happens on a particular project, Simply opening the project and clicking on "refactor" from the top menu causes the entire IDE to crash with "Embarcadero RAD Studio for Windows has stopped working, A problem caused the program to stop working correctly. Please close the program.". The same thing happens if I do "Run -> Step Over" from the top menu followed by clicking the "search" top menu entry. In both cases the top menu's pop-up doesn't show up before the crash. Doesn't happen if I open another project, but can be reliably reproduced on the problematic (larger) project every time. Anyone encountered anything like this before? I'm not even sure how to track down this issue.
  8. I was facing a similar issue with leaderboards and for cross-compatibility, decided to write a very simple back-end server of my own to maintain the leaderboard: Wrote it in Delphi+MARS and you can find it here: https://github.com/bLightZP/marsGameServices
  9. I have a usage case where my application scrapes a screenshot (thumbnail) from multiple video files in background threads. I grab the screenshot using a third party library. The problem is sometimes, the third party library will stall, usually due to a corrupt/incomplete media file where it tries to analyze the entire file (which can take upto 30 seconds). I have no way to notify the third party library to cease operations. This stalling can prevent my application from closing (It's waiting for threads to finish so the exit is clean) or even make the UI appear semi-broken because no thumbnails show up. I'd like to hear what you may have done to handle such cases?
  10. I can attest from experience that terminating threads can lead to random access violations, that's part of the reason I asked this question.
  11. Yaron

    How to close Messages window automatically

    Is it compatible with v10.3.3? Looks like last update was for 10.2
  12. Using Delphi 10.3.3 I built a simple web server using MARS Curiosity (https://en.delphipraxis.net/forum/34-mars-curiosity-rest-library/) and FireBird DB v3.0.4. However, sometimes a simple refresh in the web browser (Ctrl+R) will trigger multiple different errors: Project GameServicesServerApplication.exe raised exception class EIdSocketError with message 'Socket Error # 10053 Software caused connection abort. Project GameServicesServerApplication.exe raised exception class $C0000005 with message 'access violation at 0x00730647: read of address 0x00000000'. Project GameServicesServerApplication.exe raised exception class EDatabaseError with message 'Field 'CONSUMERNAME' not found'. Project GameServicesServerApplication.exe raised exception class EArgumentOutOfRangeException with message 'Argument out of range'. Holding Ctrl+R in the web browser easily reproduces the issue within a few seconds (the more DB calls I preform in the MARS web server function, the easier it is to trigger the crash). The fault is not in MARS, I tested by disabling all DB calls and verifying the code doesn't crash (I even threw a Sleep(1000) in there to see if it may be related to the duration it takes the function to process). Am I doing something wrong? I use a connection pool to support multiple threads connecting at once, here is how I connect to the DB: dbParams := TStringList.Create; try dbParams.Add('Server=localhost'); dbParams.Add('Database=c:\DB\Database.FDB'); dbParams.Add('User_Name=SYSDBA'); dbParams.Add('Password=SomePassword'); dbParams.Add('CharacterSet=UTF8'); dbParams.Add('Pooled=True'); FDManager.AddConnectionDef(dbPoolName,'FB',dbParams); Try FDManager.Open; Except on E : Exception do {$IFDEF TRACEDEBUG}AddDebugEntry(debugFileSystem,'Exception connecting to DB : '+E.Message){$ENDIF}; End; finally dbParams.Free; end; Here's the MARS server definition: Type [Path('test')] TGalleryServicesResource = class protected public [GET , Path('/gallery'), Produces(TMediaType.TEXT_HTML)] function Gallery_From_External_Source([QueryParam] code : String) : String; end; Here is the function MARS triggers: function TGalleryServicesResource.Gallery_From_External_Source(code : String) : String; begin If GetGalleryCodeDetails(sDebugFile,code,nGalleryCode) = True then Begin End; end; And here is the database access: function GetGalleryCodeDetails(sDebugFile,sGalleryCode : String; var nGalleryCode : TGalleryCodeRecord) : Boolean; var dbQuery : TFDQuery; begin Result := False; dbQuery := TFDQuery.Create(nil); Try dbQuery.ConnectionName := dbPoolName; dbQuery.SQL.Text := 'SELECT * FROM GALLERY_CODES WHERE CODE_UID=:gallerycodeuid;'; Try dbQuery.Prepare; dbQuery.ParamByName('gallerycodeuid').AsString := sGalleryCode; dbQuery.Open; If dbQuery.RecordCount > 0 then Begin Result := True; With nGalleryCode do Begin gcUserName := dbQuery.FieldByName('CONSUMERNAME').AsString; gcUserEMail := dbQuery.FieldByName('CONSUMEREMAIL').AsString; gcCodeUID := dbQuery.FieldByName('CODE_UID').AsString; gcImageURL := dbQuery.FieldByName('IMAGEURL').AsString; gcCreateTimeStamp := dbQuery.FieldByName('CREATE_TIMESTAMP').AsFloat; gcOpenTimeStamp := dbQuery.FieldByName('OPEN_TIMESTAMP').AsFloat; gcUseTimeStamp := dbQuery.FieldByName('USE_TIMESTAMP').AsFloat; gcStatus := dbQuery.FieldByName('STATUS').AsInteger; End; End; Except on E : Exception do {$IFDEF TRACEDEBUG}AddDebugEntry(sDebugFile,'Exception : '+E.Message){$ENDIF}; End; Finally dbQuery.Free; End; end;
  13. If anyone else is wondering how it's done, you need to add "[Context] marsRequest: TWebRequest;" and then the client's IP is available in "marsRequest.RemoteIP". [Path('projectX')] TProjectXServicesResource = class protected [Context] marsRequest: TWebRequest; public [GET, Produces(TMediaType.TEXT_HTML)] function xHome([QueryParam] lang : String) : String; [POST, Consumes(TMediaType.MULTIPART_FORM_DATA), Produces(TMediaType.TEXT_HTML)] function xAction([FormParams] AParams: TArray<TFormParam>): String; end; function TProjectXServicesResource.xHome([QueryParam] lang : String) : String; begin ShowMessage(marsRequest.RemoteIP); end; function TProjectXServicesResource.xAction([FormParams] AParams: TArray<TFormParam>) : String; begin ShowMessage(marsRequest.RemoteIP); end;
  14. @David Heffernan It's not that the code freezes forever, it stalls. Here are real-world examples, 1. A 3rd party product called ODB Studios has a bug, it does not set a timestamp for it's audio stream, so when playing a video, the entire stream must be decoded to reach the seek point (the position where I take the thumbnail). This causes the (directshow) seek command to stall for upto 60 seconds. 2. A user starts to download a video file and then pauses/stops the download (so the file is no longer locked, I postpone thumbnail generation for locked files). The video's frame-index block did not download yet, so the (directshow) file parser then scans the entire media file to reconstruct the frame-index which can easily stall for 30-60 seconds on multi-GB files. There are other cases where this issue can happen, there is no way to avoid it since I can't know in advance every case for every audio/video format that may pop-up.
  15. Looks like this issue is somewhat complex, I've actually read this article: https://www.the-art-of-web.com/sql/counting-article-views/ In which they suggest creating a separate table just for view counting, with each row representing a view (sql INSERT) and every so often running aggregation code that converts the rows into actual pageview numbers to insert into the original table and erase the counted rows. Using this method means no deadlocks are possible when counting things, might even mean less DB overhead (they write that UPDATE is slower than INSERT, but it's not something I confirmed).
  16. I'm a complete novice working with databases and like dany, I want to know how as well. I actually tried reading the documentation (https://firebirdsql.org/refdocs/langrefupd25-nextvaluefor.html) but it's pretty alien me at this point.
  17. The view number is read earlier in the code, I actually replaced it with a more reliable SQL command to increase the value instead of setting it: procedure ClubHouseDB_IncCampaignViewCount(sDebugFile,sGalleryUID : String); var dbConn : TFDConnection; dbQuery : TFDQuery; deadLocked : Boolean; begin deadLocked := False; dbConn := TFDConnection.Create(nil); dbConn.ConnectionDefName := dbPoolName; dbQuery := TFDQuery.Create(nil); dbQuery.Connection := dbConn; Try dbQuery.SQL.Text := 'UPDATE GALLERY_TABLE SET VIEW_COUNT=VIEW_COUNT+1 WHERE GALLERY_UID=:galleryuid;'; Try dbQuery.Prepare; dbQuery.ParamByName('galleryuid').AsString := sGalleryUID; dbQuery.ExecSQL; Except on E : Exception do If Pos('deadlock',Lowercase(E.Message)) > 0 then deadLocked := True; End; Finally dbQuery.Free; dbConn.Free; End; If deadLocked = True then ClubHouseDB_IncCampaignViewCount(sDebugFile,sGalleryUID); end; As you can see from the updated code, I'm catching the deadlock by looking at the returned exception message, I'm not sure it's the best approach, but I haven't been able to find another way to identify the deadlock. I don't have a problem increase the deadlock timeout, but I couldn't find anything on how to do that, I'm not even sure if it's part of the Firebird SQL statement or if I need to specify it through the Firedac components.
  18. I'm new to databases, is there any Delphi Firedac sample code that shows best practices when handles deadlocks? My deadlock is a simple integer page-view counter, here's the actual code: procedure SetCampaignViewCount(sDebugFile,sGalleryUID : String; nCount : Integer); var dbConn : TFDConnection; dbQuery : TFDQuery; begin dbConn := TFDConnection.Create(nil); dbConn.ConnectionDefName := dbPoolName; dbQuery := TFDQuery.Create(nil); dbQuery.Connection := dbConn; Try dbQuery.SQL.Text := 'UPDATE GALLERY_TABLE SET VIEW_COUNT=:viewcount WHERE GALLERY_UID=:galleryuid;'; Try dbQuery.Prepare; dbQuery.ParamByName('galleryuid').AsString := sGalleryUID; dbQuery.ParamByName('viewcount').AsInteger := nCount; dbQuery.ExecSQL; Except on E : Exception do Begin {$IFDEF TRACEDEBUG}AddDebugEntry(sDebugFile,'SetCampaignViewCount Exception : '+E.Message){$ENDIF}; End; End; Finally dbQuery.Free; dbConn.Free; End; end;
  19. Thanks, I read the FAQ entry. I'm new to working with databases, what is the best approach to deal with deadlocks? The actual DB call that triggered the deadlock was a view counter, two users viewing the same web page. What is the best approach to handle such deadlocks?
  20. My code now creates and frees both TFDConnection and TFDQuery: procedure DB_SetUserFlags(sDebugFile,sUserUID : String; iFlags : Integer); var dbConn : TFDConnection; dbQuery : TFDQuery; begin dbConn := TFDConnection.Create(nil); dbConn.ConnectionDefName := dbPoolName; dbQuery := TFDQuery.Create(nil); dbQuery.Connection := dbConn; Try dbQuery.SQL.Text := 'UPDATE USERS SET USER_FLAGS=:userflags WHERE USER_UID=:useruid;'; Try dbQuery.Prepare; dbQuery.ParamByName('userflags').AsInteger := iFlags; dbQuery.ParamByName('useruid').AsString := sUserUID; dbQuery.ExecSQL; Except on E : Exception do {$IFDEF TRACEDEBUG}AddDebugEntry(sDebugFile,'Exception : '+E.Message){$ENDIF}; End; Finally dbQuery.Free; dbConn.Free; End; end;
  21. After rewriting every DB entry point using "TFDConnections", I managed to resolve most of the errors, now I'm only receiving these 2: Project GameServicesServerApplication.exe raised exception class EIdSocketError with message 'Socket Error # 10053 Software caused connection abort. Project GameServicesServerApplication.exe raised exception class EIBNativeException with message '[FireDAC][Phys][FB]deadlock I'm assuming the first error is due to constant reloads in browser (it only happens in a browser, doesn't happen for me when load-testing using threads). However, the "deadlock" exception is an issue, any ideas why it's triggered and how to avoid it?
  22. You may be right, I was basing my code on a comment by Jacek here It's quite possible he was wrong, initial testing looks to confirm this.
  23. I even created a simple load-testing app (https://github.com/bLightZP/Web-Server-Load-Tester) that opens the URL in multiple threads simultaneously (triggers the crashes instantly). With 10 thread it crashes instantly if there's DB access, if I disable the DB access code, even 1000 threads work just fine. And even with just 2 threads it can occasionally crash.
  24. The painful thing about this experimentation is that it wipes my editor color selection each time I try something. I simply can't understand some Embarcadero's UI choices 😞
  25. I'm aware that with recent versions, the theming has been rewritten so I'm wondering if there's any tool/editor supporting the latest Delphi theming features that would let me specify my own RGB values for each UI element. I would like to create an alternative dark theme that's more utilitarian. While I prefer a dark theme for eye strain, I find the current dark theme too flat with UI elements that I expect to be on a different plane (color) becoming merged visually (e.g. Scrollbars widgets). I'm aware there are a few other dark'ish themes included, but they too suffer from their own issues so I would rather create (and share of course) my own color-theme.
×