10 Reasons to Use PAServer for Remote Windows Deployment

Everyone knows PAServer (Platform Assist Server) is the easy way to deploy and debug multi device apps from Windows to Apple OS X and iOS. It handles all the bundling and deployment from your Windows development platform across the network, via a virtual machine, or even to the cloud.

Previously I showed you how to connect to a Android Emulator on another machine (or outside your VM), but did you know you can also use the PAServer to deploy and debug against a remote Windows machine? It isn’t required, so isn’t as immediately obvious, but it is supported and pretty easy to setup.

If you are already developing on a Windows machine, why us PAServer to test against a remote Windows machine? There are a lot of reasons, here are a few . . .

  1. Testing on machine without IDE installed
  2. Windows tablets
  3. Different CPU architectures (64-bit vs 32-bit)
  4. Different numbers of cores
  5. Utilizing specialized hardware
  6. Running outside / inside a virtual machine
  7. Deployment on a server (remote, local, in the cloud)
  8. Debugging on more than one version of Windows
  9. Debugging issue that only occurs on one machine
  10. Bundled deployment options

Now that we see the need, how do we do it?

Install PAServer on the target Windows computer. You can find it at C:\Program Files (x86)\Embarcadero\Studio\17.0\PAServer if you used the default install location during your original install. When installing PAServer, you either need to use a different install location (to a user writable folder), or specify a custom scratch-directory, as the default is not writable (unless you run PAServer as Administrator) and will give you an E0009 PAClient Error. Once PAServer is setup just run it.

Custom PAServer Install Destination

Use the Connection Profile Manager to create a new Windows profile.

RAD Studio Connection Profile Manager

Instead of the default of OS X, choose either Windows 32-bit or 64-bit. The rest of the configuration is the same.

Create Windows 64-bit Profile Connection

Then form the Project Manager, right-click on the Windows platform you want to deploy remotely, and select properties.

Project Manager - Platform Properties

And then select the new connection you want.

Platform Properties - Select Profile

This works with any project type (FireMonkey, VCL, Console, etc.)

Profile Selected

Now you can also use the Deployment Manager for Windows apps as well.

Posted in News, Tools | Tagged , , , , , | Leave a comment

Decompressing the TRESTResponse

RAD Studio, Delphi and C++ 10 Seattle has a fantastic REST Client Library. If you are unfamiliar with it, check out my 5 Minute REST Client video.

The TRESTRequest component has an AcceptEncoding property where you can specify the type of compression you would like applied to the response. The TRESTResponse component has a ContentEncoding property that specifies the the encoding that the server chose. The most common compression encoding is gzip, followed by deflate. The others are rarely used (although brotli is a new compression that looks promising for the future.)

By default it is not encrypted if you leave AcceptEncoding blank. However when you use the Stack Overflow API it always compresses with gzip if nothing is specified.

The TRESTResponse has two ways to access the response data directly, the RawBytes property and the Content property. Both are read-only. So we can read the compressed response data, but cannot update the TRESTResponse with the decompressed data. Updating the TRESTReponse allows it to work with the TRESTResponseDataSetAdapter, which is a fantastic feature.

Luckily we can use the protected mode workaround to update the value. Here is a unit that you can include in your project to easily decompress the TRESTResponse and continue to use it with the Data Set Adapter.

unit RestDecompress;

interface

uses
  System.SysUtils, System.Types, System.Classes, IPPeerClient, REST.Client;

procedure DecodeRestResponse(ARestResponse: TRESTResponse);

implementation

uses
  System.Zlib,
  IdBaseComponent, IdException, IdZLibCompressorBase, IdCompressorZLib;

  type // protected mode work around
  TProtectedRESTResponse = class(TRESTResponse)
  end;


procedure DecodeRestResponse(ARestResponse: TRESTResponse);
var
  LCompressed: TMemoryStream;
  LDecompressed: TStringStream;
  LDecompress: TIdCompressorZLib;
begin
  if Length(ARestResponse.ContentEncoding) = 0 then exit;

  LCompressed := nil;
  LDecompressed := nil;
  LDecompress := nil;
  try
    LCompressed := TMemoryStream.Create;
    LDecompressed := TStringStream.Create;

    LCompressed.WriteData(ARESTResponse.RawBytes, Length(ARESTResponse.RawBytes));
    LCompressed.Position := 0;

    // Use the Indy decompression libraries because the HTTP stream doesn't
    //   have the proper headers that System.ZLib looks for.

    LDecompress :=TIdCompressorZLib.Create();

    if ARestResponse.ContentEncoding = 'gzip' then
      LDecompress.DecompressGZipStream(LCompressed, LDecompressed)
    else if ARestResponse.ContentEncoding = 'deflate' then
    begin
      // Due to variations in the deflate server side implementations,
      //   this rarely works, but is here for completeness and just in case
      LDecompress.DecompressHTTPDeflate(LCompressed, LDecompressed);
    end;

    TProtectedRESTResponse(ARESTResponse).SetContent(LDecompressed.DataString);
  finally
    LDecompressed.Free;
    LCompressed.Free;
    LDecompress.Free;
  end;
end;

end.

Simply use this unit, and then add a call to DecodeRestResponse(RESTResponse) to RESTResponse’s OnAfterExecute event handler. It checks the ContentEncoding and then uses the correct decompression and updates the content.

You’ll notice it uses the Indy TIdCompressorZLib component instead of the new System.ZLib library. The reason is a GZip encoded HTTP response doesn’t include the full headers expected by the ZLib library. There is a way to work around this, but no need to do that since the Indy library works fine.

Posted in REST | Tagged , , , , , , | 2 Comments

What MVPs Are Saying about Delphi and C++Builder 10 Seattle

Our Embarcadero MVPs are all over the world, and a few of them wanted to share their impressions of Delphi and C++Builder 10 Seattle.

Jens Fudge, Archersoft Aps in Denmark says:

Delphi 10 Seattle is a great product. My favourite development tool indeed, with many nifty utilities that you need to know

Raouf Rahiche in Algeria has a review in Arabic

Roman Kassebaum from Germany, the maintainer of TurboPack, reports on libraries updated to Delphi and C++Builder 10 Seattle.

Radek Cervinka from Czech Republic has a few Delphi 10 Seattle related posts.

Sanghyun Oh of Devgear in Seoul, Korea has some Delphi 10 Seattle related posts in Korean.

Danny Wind of the Delphi Company in Netherlands has some posts on Delphi 10 Seattle in Dutch.

Victory Fernandes of TKS in Salvador Brazil says:

New Delphi 10 Seattle rocks! Spreading the word about Delphi in Brazil!

Xavier Martinez from Andorra has a review on Delphi 10 Seattle in English and in Spanish.

As you can see, the list of improvements is long, so I encourage you to try this new version of Delphi.

Eliseo Gonzalez Nieto of Sistemas CASA in Mexico says the following (Spanish):

Delphi 10 Seattle es la versión que mas me ha gustado por todas las mejoras que se han agregado, destacando la liberación de la RTL que nos permitirá desarrollar aplicaciones listas para Windows 10.

Bruno Fierens of TMS Software in Belgium has their full range of components and libraries updated to work with Delphi and C++Builder 10 Seattle. [Blog in English]

Marcos Antonio Moreira of Unimed Gov. Valadares in Brazil reports:

 The RAD Studio 10 Seattle is fantastic. Its integration with Windows 10 and all the new features that have been incorporated into the tool such as improvements in the IDE, compilers, connectivity and productivity make this the most complete version for Windows development, Mobile and IoT.

Didier Cabalé of DCConseil in France has updates about Delphi 10 Seattle in English.

Landerson Gomes dos Santos in Rio de Janeiro, Brazil says (In Portuguese):

Desde seu lançamento no dia 31 de agosto de 2015, o RAD Studio 10 Seattle vem conquistando o cenário de desenvolvimento rápido de aplicações, acredito eu que nunca um lançamento de versão do RAD foi tão aguardado e comentado como esse.

What do you think of Delphi, C++Builder and RAD Studio 10 Seattle?

Posted in MVP | Tagged | 3 Comments

Skill Sprint: Using FireMonkey Layouts

FireMonkey has many layout controls to choose from. Come learn the differences and how to use them to create dynamic, multi-platform user interfaces.

FireMonkey Layouts with Delphi

FireMonkey Layouts with C++Builder

 

Understanding and using FireMonkey Layouts

FireMonkey and the FireUI makes it easy to build one form to rule all the platforms. Combining layout controls and making use of Anchors, Alignment, Padding and Margins it is easy to make one form that looks and works great on all platforms.

Anchors

  • Position relative to one or more edge(s) of parent:Anchor
    • Top
    • Bottom
    • Left
    • Right
  • Default is Top, Left
  • Moves with parent resize
  • Each control has 0 to 4 anchors

Alignment

  • Aligns control within parent, setting anchors, size and position.
  • Default is None.
  • Anchor and fill along edge:
    • Top, Bottom, Left, Right
  • Fill parent, but preserve aspect ratio:
    • Fit, FitLeft, FitRight
  • Fill along one side of the parent (priority over other edge alignments):
    • MostBottom, MostTop, MostLeft, MostRight
  • Resize only on one axis (width or height)
    • Vertical, VertCenter, Horizontal, HorzCenter
  • Miscellaneous
    • Client – Fills client area, less other children
    • Center – No resize, just centered
    • Contents – Fills client area, ignoring other children
    • Scale – resizes and moves to maintain the relative position and size

Spacing – Margins and Padding

  • MarginsMarginsAndPadding
    • Spacing for siblings (and parent edges)
  • Padding
    • Spacing for children

TFlowLayout

  • Arrange child controls like words in a paragraph
  • Controls arranged in order added to layout
    • Use “Move to Front” or “Send to Back” to reorder
  • Use TFlowLayoutBreak for forced line break

FlowLayout1 FlowLayout2

TGridLayout

  • Arranges child controls in a grid of equal sizes
  • Controls flow through grid as parent resizes
  • Use ItemWidth and ItemHeight properties
  • Customize margins of individual controls

GridLayout2 GridLayout1

TGridPanelLayout

  • Creates a grid of specified rows and columns
  • Does not change the anchor or size of child
  • Each cell can contain 1 child control
  • You set the Height, Width, Align, and Anchors of children
  • Controls can span multiple cells

GridPanelLayout2 GridPanelLayout1

TScaledLayout

  • Stretches child controls as it is resized at runtime
  • Doesn’t respect aspect ratios of controls
  • Set the Align of the TScaledLayout to Fit to maintain aspect ratio
  • Some styles look better zoomed than others. The font grows – it is not a bitmap scale.
  • Has properties for OriginalWidth and OriginalHeight – Compare to Width and Height to determine scaling.

ScaledLayout-Stretch

TScrollBox

TTabControl

  • Control to group child controls into tabs
  • Tabs are in a stack with one visible at a time
  • TabPosition := PlatformDefault to use platform default behavior
  • TabPosition := None to hide navigation
  • Use TTabChangeAction to animate transitions

Frames

  • Reusable pieces of User Interface
    • Includes
      • The layout
      • All the event handlers
      • All the code in the unit
  • Create 1 or more Frames, then reposition based on current layout
    • Examples:
      • In TTabControl for phone
      • Side-by-side for Tablet

TMultiView

  • One super panel with multiple modesMultiView
  • Supported modes
    • PlatformDefault
    • Drawer
    • NavigationPane
    • Panel
    • Popover
    • Custom
  • Point to MasterPane, DetailPane and definable MasterButton
  • PlatformDefault adapts to platform and orientation
  • Custom supports user defined layout and behavior

Learning Resources

ScaledLayout Helper

The AbsoluteToLocal and LocalToAbsolute for TScaledLayout don’t handle the scaling. I’ve created a class helper that adds new methods for dealing with scaling.


{ TScaledLayoutHelper - interface } 

type 
  TScaledLayoutHelper = class helper for TScaledLayout 
    function LocalToAbsoluteScaled(const Point: TPointF): TPointF;
    function AbsoluteToLocalScaled(const Point: TPointF): TPointF; 
  end; 

{ TScaledLayoutHelper - implementation } 

function TScaledLayoutHelper.AbsoluteToLocalScaled( const Point: TPointF): TPointF; 
begin 
  Result.X := Self.Position.X 
              + Point.X 
              * Self.Width 
              / Self.OriginalWidth; 
  Result.Y := Self.Position.Y 
              + Point.Y 
              * Self.Height 
              / Self.OriginalHeight; 
end; 

function TScaledLayoutHelper.LocalToAbsoluteScaled( const Point: TPointF): TPointF; 
begin 
  Result.X := Point.X 
              / Self.Width 
              / Self.OriginalWidth 
              - Self.Position.X; 
  Result.Y := Point.Y 
              / Self.Height 
              / Self.OriginalHeight
              - Self.Position.Y; 
end; 

If you look at the original implementations of AbsoluteToLocal and LocalToAbsolute you will see they have different execution paths and calculations based on private members, so there may be some circumstances where my new ones don’t work as expected. They did work in my tests, and I am open to feedback.

Posted in webinar | Tagged , , | 1 Comment

Hour of CodinGame with Object Pascal / Delphi

Hour of Code is upon us again. Take some time to learn about programming, or share what you know with others. In this blog post I show how the side CodinGame helps teach Delphi and also provide some resources for those wanting to learn programming.

A short overview to CodinGame for Hour of Code

CodinGame uses Free Pascal behind the scenes, which is based on Delphi. This means it is actually Object Pascal, which is an extension on Pascal. The code I’ve seen on CodinGame is mostly plain procedural Pascal, but since it is using an actual compiler, you should be able to use full Object Pascal. You will however be limited because Free Pascal doesn’t support some of the latest features Delphi does. Still a good learning resource and a lot of fun.

I’m planning to sit down with each of my kids, and probably my wife, on CodinGame this week! If you already know how to code then find someone you can share with too!

Resources for CodinGame and Hour of Code: 

Posted in webinar | Tagged , , , , | Leave a comment

How to Reference a Procedure

It was pointed out in the comments and on G+ that this covers type aliases, but not procedure aliases. Instead it shows how to have a variable that references a procedure and then allows you to call it by this new variable. While I used alias as meaning “reference by a different name” it does in fact have a specific definition in this context. Sorry if there was any confusion or undue frustration at imprecise terminology.

I just answered a question about how to alias a procedure. I thought it was interesting enough to share here.

It is easy enough to alias a type . . .

type
  my_integer = integer;

then we can just use my_interger in place of integer as a type. But what about a procedure (or function for that matter)?

There are two different ways, depending on if the procedure is a member of a class. For straight up procedural procedures and functions it looks a little something like this:

procedure HelloWorld; // declare our procedure
begin
  ShowMessage('Hi');
end;

var
  my_proc: Procedure; // declare our alias

begin
  my_proc := HelloWorld; // assign the alias
  
  // ...

  if assigned(my_proc) then // verify the reference
    my_proc; // call the alias
end;

This is pretty straight forward. We just create an alias reference variable of the right type, and assign it to the procedure we want to alias reference. If you call an alias reference variable that is unassigned you will get a null reference access violation.

You can also streamline it a little like this

var // or as const
  my_proc: procedure = HelloWorld;

Then you know it is assigned. I guess this would be useful if you want to alias reference a procedure declared in a different unit.

This works the same for functions or procedures with parameters.

procedure Hello(name: String);
begin
  ShowMessage('Hello ' + name);
end;

function Nine: integer;
begin
  Result := 9;
end;

var
  argumentative: procedure(s: string) = Hello;
  number: function: integer = Nine;

Notice that the name of the argument doesn’t have to match, but the number, order and types do. If they don’t then you will get the error

E2009 Incompatible types: ‘Parameter lists differ’

Now what if you are dealing with procedures or functions that are members of an object? If you try to assign them to the above types you will get the error

E2009 Incompatible types: ‘regular procedure and method pointer’

And that is because members of an object are method pointers. Fear not, you can handle them with just a slightly different type declaration:

type
  TMethod = procedure of object;
  TFunc = function: integer of object;
  TNotifyEvent = procedure(Sender: TObject) of object;

In this case they are declared as types with “of object” added to the end. This indicates that they are procedures of an object. AKA members or method pointers.

You can read more about procedural types and method pointers in the DocWiki.

Why would you want to do any of this? First of all, the method pointer is how the VCL & FMX handles dependency injection through event handlers. This is also really useful when combined with anonymous methods and the parallel programming library.

Posted in Source Code | 6 Comments

Podcast Episode 60 – Victory Fernandes

In this episode I talk with Embarcadero MVP Victory Fernandes from Salvador, Brazil. While Victory is from Brazil, he also speaks fluent English.

Victory Fernandes

Victory talks about:

Most all of Victory’s projects are powered by Delphi and InterBase with emphasis on embedded and real-time application development.

Posted in Audio podCast, podcast | 1 Comment

REST Client Video Challenge

Yesterday, I mentioned I built a REST client and deployed it to iOS and Android inside 5 minutes. Someone asked me to make a video actually showing how it was done. So here it is showing a simple REST client built and deployed to iOS 9.1 and Android 6.0 Marshmallow.

Since I am using SpitCast, and it doesn’t offer an encrypted endpoint for its REST service, I had to modify the Info.plist to allow that on iOS 9.

Could I do it faster without the video recording and explanation? Yes, but I think you get the idea. Delphi makes building multiplatform REST clients really, really easy.

I’m curious to see someone create a client app using other general purpose development tools to connect to a REST service and too see how long that takes.

If I wanted to connect to a different end point to pull down more information on an individual surf spot I could that by handling the OnItemClick event for the List View.

If there is interest I’m happy to share my Sync-Timer source code.

Posted in Android, iOS, Mobile, REST | 2 Comments

Delphi and REST Client Development

I really don’t like to make comparison between different development tools. In my opinion most tools have their strengths for certain tasks. So I try not to criticize other tools by name. Delphi is my favorite, and I believe it is the best all around tool for more projects I face. Occasionally I have someone ask me how Delphi compares to another tool they are evaluating. I thought I would share one such experience.

When I was in Brazil I went to meet with a guy who was in charge of software development for a large, international company. They were all standardized on a different development tool, but it didn’t really have a mobile solution. They were looking at some tools that claimed to make it really easy to do mobile development, but once he got past the marketing he found it wasn’t all it was cracked up to be.

To evaluate the tool he decided he would develop a simple little app for iPhone and Android that connected to a REST server to pull down a list of countries, cities, etc. to help people find offices for his company. He thought that a week should be more then enough time to develop this simple application.

What he found was that while he expected it to be cross platform, it was actually only shared code. So he had to create a project for each platform, and then he could share part of the code (not as much as he would like) between each project. Also there was significant overhead in consuming a REST service. After a couple days he realized a week wasn’t enough time for even one platform.

To top it all off he discovered that the cost was actually way more then it was initially made out to be when you actually got down to doing something serious.

So I showed him Delphi and told him that the app he was describing could be done inside a day, probably with a prototype within an hour. He found that a little hard to believe, so I created a simple REST client displaying the result of a REST service and deployed it to my Android phone. It took about 5 minutes, including the time it took to connect to his WiFi.

He was so impressed he actually got his phone out to make a video of it just so he could show his boss, who he was sure wouldn’t believe him.

That is what I love about Delphi. It makes the simple things that you need to do all the time so simple and so quick, and it makes everything else still pretty simple. Need an API that isn’t wrapped in a component or the RTL, no problem, you can still access it.

Posted in REST, Tools | Tagged | 11 Comments

Android Services Presentations and Workarounds

Another round up of Android Service related resources.

For starters here are my slides from my Android Services presentation in Brazil.

You can also download the Workarounds and fixes for the Java templates and Android Manifest from CodeCentral.

You can catch a replay of Julian Mesa’s session from CodeRage X

And check out my other Android Services posts.

Posted in Android, Conferences | Tagged | Leave a comment