Jump to content

Ruslan

Members
  • Content Count

    43
  • Joined

  • Last visited

Posts posted by Ruslan


  1. Hi all and Happy Holidays!

     

    Can anyone guide me how to use Kastri or native FMX for making and receiving calls from application?

    Also I need a method to control the calling process, eg to terminate the call after some seconds, and to get statuses (logs) for those calls (answered, no answer, invalid number, or any type of calling results).

     

    I've started with PhoneDialer example that came with Delphi, and tried to use smth like following example but can't get statuses.

     

    procedure TPhoneDialerForm.FormCreate(Sender: TObject);
    begin
    {$IFDEF ANDROID}
      FCallPhonePermission := JStringToString(TJManifest_permission.JavaClass.CALL_PHONE);
      FReadPhoneStatePermission := JStringToString(TJManifest_permission.JavaClass.READ_PHONE_STATE);
      FReadCallLogPermission := JStringToString(TJManifest_permission.JavaClass.READ_CALL_LOG);
      FManageOwnCalls := JStringToString(TJManifest_permission.JavaClass.MANAGE_OWN_CALLS);
      FBindTelecomService := JStringToString(TJManifest_permission.JavaClass.BIND_TELECOM_CONNECTION_SERVICE);
      //FReadPrecisePhoneState := JStringToString(TJManifest_permission.JavaClass.READ_PRECISE_PHONE_STATE);
    {$ENDIF}
    
      { test whether the PhoneDialer services are supported }
      TPlatformServices.Current.SupportsPlatformService(IFMXPhoneDialerService, FPhoneDialerService);
    
      PermissionsService.RequestPermissions([FCallPhonePermission,FReadPhoneStatePermission,FReadCallLogPermission,FManageOwnCalls,FBindTelecomService],
        procedure (const APermissions: TClassicStringDynArray; const AGrantResults: TClassicPermissionStatusDynArray)
        begin
          if (Length(AGrantResults) = 5) and
             (AGrantResults[0] = TPermissionStatus.Granted) and
             (AGrantResults[1] = TPermissionStatus.Granted) and
             (AGrantResults[2] = TPermissionStatus.Granted)
             and (AGrantResults[3] = TPermissionStatus.Granted)
             and (AGrantResults[4] = TPermissionStatus.Granted)
          then begin
            ShowMessage('Permissions Activated!');
          end;
        end
      );
    
      FPhoneDialerService.OnCallStateChanged := CallStateChanged;
    end;
    
    procedure TPhoneDialerForm.CallStateChanged(const ACallID: string;
      const AState: TCallState);
    var
      Calls: TCalls;
      Call: TCall;
    begin
      case AState of
        TCallState.None: begin
          lbCalls.Items.Add(Format('%-16s %s', [ACallID, CallStateAsString(AState)]));
        end;
        TCallState.Connected: begin
          lbCalls.Items.Add(Format('%-16s %s', [ACallID, CallStateAsString(AState)]));
        end;
        TCallState.Incoming: begin
          Calls := FPhoneDialerService.GetCurrentCalls;
          try
            for Call in Calls do
            begin
              if Call.GetCallID = ACallID then
              begin
                lbCalls.Items.Add(Format('%-16s %s', [ACallID, CallStateAsString(AState)]));
    
                Exit;
              end;
            end;
          finally
            for Call in Calls do
              Call.Free;
          end;
        end;
        TCallState.Dialing: begin
          lbCalls.Items.Add(Format('%-16s %s', [ACallID, CallStateAsString(AState)]));
        end;
        TCallState.Disconnected: begin
          lbCalls.Items.Add(Format('%-16s %s', [ACallID, CallStateAsString(AState)]));
        end;
      end;
    end;
    
    function TPhoneDialerForm.CallStateAsString(AState: TCallState): String;
    begin
      case AState of
        TCallState.None:
          Result := 'None';
        TCallState.Connected:
          Result := 'Connected';
        TCallState.Incoming:
          Result := 'Incoming';
        TCallState.Dialing:
          Result := 'Dialing';
        TCallState.Disconnected:
          Result := 'Disconnected';
      else
        Result := '<unknown>';
      end;
    end;

    For the calling method I used these

    // Default method from example
    procedure TPhoneDialerForm.btnMakeCallClick(Sender: TObject);
    begin
      { test whether the PhoneDialer services are supported }
      if FPhoneDialerService <> nil then
      begin
        { if the Telephone Number is entered in the edit box then make the call, else
          display an error message }
        if edtTelephoneNumber.Text <> '' then begin
          PermissionsService.RequestPermissions([FCallPhonePermission], MakePhoneCallPermissionRequestResult, DisplayRationale)
          //FPhoneDialerService.Call(edtTelephoneNumber.Text);
        end
        else
        begin
          TDialogService.ShowMessage('Please type in a telephone number.');
          edtTelephoneNumber.SetFocus;
        end;
      end
      else
        TDialogService.ShowMessage('PhoneDialer service not supported');
    end;
    
    procedure TPhoneDialerForm.MakePhoneCallPermissionRequestResult(Sender: TObject; const APermissions: TClassicStringDynArray; const AGrantResults: TClassicPermissionStatusDynArray);
    begin
      // 1 permission involved: CALL_PHONE
      if (Length(AGrantResults) = 1) and (AGrantResults[0] = TPermissionStatus.Granted) then
        FPhoneDialerService.Call(edtTelephoneNumber.Text)
      else
        TDialogService.ShowMessage('Cannot make a phone call because the required permission has not been granted');
    end;
    
    // The other method for making calls
    procedure TPhoneDialerForm.MakeCall(const PhoneNumber: string);
    var
      Intent: JIntent;
      Uri: Jnet_Uri;
    begin
      Intent := TJIntent.Create;
      Intent.setAction(TJIntent.JavaClass.ACTION_CALL);
      Uri := TJnet_Uri.JavaClass.parse(StringToJString('tel:' + PhoneNumber));
      Intent.setData(Uri);
    
      if TAndroidHelper.Activity.getPackageManager.queryIntentActivities(Intent, 0).size > 0 then
        TAndroidHelper.Activity.startActivity(Intent)
      else
        ShowMessage('No app to handle the call intent.');
    end;

     


  2. There is a way to encrypt the Firebird database, the is a sample in Firebird documentation.

    Unlucky me I wasn't able to create a encryption/decryption module for Firebird, most because of no time, maybe you could try to create one and share the results and will have a lot of thanks and appreciations for that.

    Most encryption/decryption modules prices are tooo big.


  3. SET SQL DIALECT 3;
    
    CREATE GENERATOR GEN_RECORD_NUMBER;
    
    SET TERM ^ ;
    
    CREATE OR ALTER TRIGGER ORDEN_BI FOR ORDEN
    ACTIVE BEFORE INSERT POSITION 0
    as
    begin
      if ((new.number is null) or (new.number = 0))  then
        new.number = gen_id(GEN_RECORD_NUMBER,1);
      if ((new.guid is null) or (trim(new.guid) = '') ) then
        new.guid = '{' || uuid_to_char( gen_uuid() ) || '}';
    end
    ^
    SET TERM ; ^

    I also use a GUID column as a unique field


  4. Delphi 10.3.3

    SOAP Server (unknown source but the server has it's a php)

    Imported the wsdl, no changes made to the unit.

    Tested requests to the server with SoapUI and everything goes fine, from Delphi application - there is no luck. All responses are about Schema mismatch.

    Using event HTTPRio.onBeforeExecute checked the request and it is the same as tested in SoapUI.

     

    Questions:

    How to debug a request?

    How to check if the request meets the schema rules?

    Any advanced docs/video on how to build SOAP client/server applications?


  5. Try to add BEGIN END for SUSPEND

    CREATE PROCEDURE "CUSTITEMMOVEMENT" 
    (
      "CUSTNO" INTEGER
    )
    RETURNS
    (
      "RNO" INTEGER,
      "TNAME" VARCHAR(5),
      "TDATE" DATE,
      "DOCNO" VARCHAR(12),
      "QTY" NUMERIC(18, 2),
      "NETPRICE" NUMERIC(18, 4),
      "ITEMNO" VARCHAR(20),
      "ITEMNAME" VARCHAR(40)
    )
    AS
     BEGIN
        FOR SELECT  IM.RNO,IM.TNAME,IM.TDATE,IM.DOCNO,IM.QTY,
        IM.NETPRICE,IM.ITEMNO, IT.ITEMNAME
        FROM ITEMMOVEMENTS IM
        JOIN ITEMS IT ON IT.ITEMNO=IM.ITEMNO
        WHERE (IM.CUSTNO= :"CUSTNO")
        ORDER BY IM.TDATE, IM.DOCNO
        INTO :"RNO",:"TNAME",:"TDATE",:"DOCNO",:"QTY",:"NETPRICE",:"ITEMNO",:"ITEMNAME"
        DO BEGIN
          SUSPEND;  /* Line 26 is here */
        END  
    END ; 

     


  6. Is you are using FireDAC than transactions are used internally, but you could use transactions like in your example.

    The "commit" is required if the the DataSet is set to no auto commit, e.g. cached updates.

     

    If I am wrong please correct me.


  7. I am trying to Internationalize a application using integrated Delphi feature using documentation.

    After the application is created I use "Resource DLL Wizard" and translated obtained forms.

    In documentation it is said that the application will automatically be translated by system locale settings, but also I would like to change the UI language from application settings.

    To test the application in different language I set the language from Project->Languages->Set Active, all builds and compiles but not working, an execution error rises

    Exception EResNotFound in module ExHome.exe at 00250A7D.
    Resource TfrmFDGUIxFormsError not found.
    Exception EClassNotFound in module ExHome.exe at 00065F62.
    Class TFDGUIxErrorDialog not found.

    Don't know how to fix that. Tried to remove FDGUIxWaitCursor and FDGUIxErrorDialog from project datamodule, but no luck.

     

    And the second question is how to change the language from application settings and use that language on next start?

    Can I save the current application language in a INI file?

    And how to add other translations for strings (messages, exceptions, etc.) used in units?

     

    Delphi 10.3

    Application with FireDAC SQLite database


  8. Never worked with SQLite before and now for my project need to use it but some questions and misunderstandings came on application model (VCL).

    1. I used to use GUID data type for unique records, in SQLite table the field 'uuid' is declared as binnary 'guid', and I created a trigger to generate the value, in application in FDConnection.Params.GUIDFormat=guiBinary, but when try to execute a clean FDQuery a message shows up:
      [FireDAC][DatS]-10. Fixed length column [uuid] data length mismatch. Value length - [32], column fixed length - [16].

      changing FDConnection.Params.GUIDFormat=guiString show up a 'Wrong guid format error'.
      and here is the trigger for guid generation:

      CREATE TRIGGER demotable_after_insert AFTER INSERT ON demotable 
      FOR EACH ROW
      WHEN (NEW.uuid IS NULL)
      BEGIN
      	UPDATE demotable SET uuid = lower(hex(randomblob(16))) WHERE id = NEW.id;
      END

      So the question is how to deal with guids in Delphi+SQLite? Should I generate them from application? Do I need to make some mappings?

    2. The second question is about using generators for auto incremented fields, is this possible?


  9. Think VM as a computer, it's not a container (like docker or jail), so if you think of moving the IDE to the VM than you should move the project(s) to othe VM and all the dev tools needed for that project.

    I did like that. I've created a VM for Delphi development only, put my Delphi projects there and all the dev tools I need for my projects development, configured the git (git+TurtoiseGit+Bitbucket) and a additional a backup method. Every time I want to make some changes to my system (not in development manner), OS upgrade, IDE upgrade/downgrade - I make a full copy of my VM (because I have only a VMWare Player), but if you have a VMWare Workstation you could use the VM snapshot that is much comfortable.


  10. The question is good, an it is hard to answer.

    First of all you need to define/create the architecture of the cloud model, to specify the services you need and how to interact with each other, to take care of load balancing and resource consumption.

    When I migrated my desktop app to the cloud the first this I've done is splitting the functionalities of my app, not all but some (btw I use Amazon AWS and Digital Ocean, but not hard to do in in Azure too). Then create a cloud infrastructure model to chose the right cloud service to you app functionality, the best example here is the database and a rest api server. Also need to remember of security.

    In the end I've came out with a simple desktop application (because some of functionalities are translated to cloud services) the connects to the cloud and is secure, load balanced, and works from anywhere in the world.

     

    But, the easier and simple way is:

    1. Buy a vps with needed OS
    2. Put you application in there
    3. And run it

     


  11. Maybe a stupid question but not for me at the moment.

    Need a way to draw rectangles on a canvas and then to make it possible to resize, move, delete or clone. That is needed to automate some process of segmentation objects (same kind of objects by rectangles with same aspect ratio) on a bunch of images (>100K).

    For now I can draw rectagles on a TImage canvas wthout any questions. But can't figure out how to select that rectangle with mouse, resize it, scale it and move.

    Or maybe should I look at shapes?

×