Skip to content

Multi-tier com Delphi XE6 e FireDAC JSON Reflection

Introdução

Durante o Delphi Tour prometemos falar mais sobre o novo suporte a Reflection no FireDAC para o desenvolvimento de aplicações Multi-tier.

Este novo suporte foi introduzido ainda na versão XE5 Update 2, como você pode observar neste post introdutório do Marco Cantu.

Vamos detalhar um pouco mais este framework e também mostrar como adicionar compressão de dados a este cenário, ideal para conexões "não muito boas" (leia-se conexõe 3G…).

Este demo pretende ilustrar um guia inicial de boas práticas com FireDAC Reflection. Ele também será utilizado em posts futuros mostrando deployment, inclusive para Apache:

Visão Geral do Projeto Exemplo

O exemplo base que utilizaremos aqui encontra-se disponível nos demos do Delphi em "C:\Users\Public\Documents\Embarcadero\Studio\14.0\Samples\Object Pascal\DataSnap\FireDACJSONReflect", mas vamos disponibilizar uma cópia atualizada contendo as adições deste post.

Esta é a estrutura do projeto exemplo:

A aplicação server é criada através do wizard "DataSnap WebBroker Application". Para o exemplo estamos utilizando uma aplicação "Stand Alone" VCL (a partir do XE6 pode ser também FireMonkey), porém você ainda tem as opções Apache e IIS, além de uma aplicação do tipo "console".

Nosso servidor vai acessar uma base exemplo do Interbase (EMPLOYEE). Serão basicamente três consultas SQL, as quais serão "exportadas" via JSON para a aplicação cliente. Abaixo você pode observar a conexão FireDAC (FDConnection) e as três consultas (FDQuery). Caso não conheça FireDAC, este webinar pode lhe ajudar: http://forms.embarcadero.com/LA14Q1BRBDEApplicationstotheFuture

Conforme comentado acima, os datasets resultantes serão exportados como JSON para a aplicação cliente. Abaixo segue o código exemplo de uma das funções criadas no servidor, todas as demais seguem o mesmo padrão de codificação:

function TServerMethods1.GetDepartmentNames: TFDJSONDataSets;
begin
 FDQueryDepartmentNames.Active := False;

 Result := TFDJSONDataSets.Create;
 TFDJSONDataSetsWriter.ListAdd(Result, FDQueryDepartmentNames);
end;

Observe que você não precisa se preocupar em converter o DataSet para JSON manualmente, a classe auxiliar "TFDJSONDataSetsWriter" possui um método (Add) que vai automaticamente serializar o DataSet em formato JSON e adicioná-lo ao Result, que por sua vez trata-se de um TFDJSONDataSets (basicamente uma lista de DataSets em formato JSON). Todas estas novas classes estão declaradas na unit "Data.FireDACJSONReflect".

Por tratar-se de uma lista de DataSets, você pode retornar em um mesmo método diversos DataSets, como por exemplo:

function TServerMethods1.GetDepartmentEmployees(
  const AID: string): TFDJSONDataSets;
begin
  FDQueryDepartmentEmployees.Active := False;
  FDQueryDepartmentEmployees.Params[0].Value := AID;

  FDQueryDepartment.Active := False;
  FDQueryDepartment.Params[0].Value := AID;

  Result := TFDJSONDataSets.Create;

  TFDJSONDataSetsWriter.ListAdd(Result, sDepartment, FDQueryDepartment);
  TFDJSONDataSetsWriter.ListAdd(Result, sEmployees, FDQueryDepartmentEmployees);
end;

Outro método que gostaria de comentar é o responsável por aplicar as alterações retornadas pelo "client" diretamente no banco de dados:

procedure TServerMethods1.ApplyChangesDepartmentEmployees(
  const ADeltaList: TFDJSONDeltas);
var
  LApply: IFDJSONDeltasApplyUpdates;
begin
  LApply := TFDJSONDeltasApplyUpdates.Create(ADeltaList);

  LApply.ApplyUpdates(sDepartment, FDQueryDepartment.Command);

  if LApply.Errors.Count = 0 then
    LApply.ApplyUpdates(sEmployees, FDQueryDepartmentEmployees.Command);

  if LApply.Errors.Count > 0 then
    raise Exception.Create(LApply.Errors.Strings.Text);
end;

A aplicação cliente envia um "TFDJSONDeltas" para o server. Basicamente temos que instanciar um "IFDJSONDeltasApplyUpdates" e aplicar as alterações nos Datasets originais através do método "ApplyUpdates".

Para a aplicação cliente, qualquer plataforma pode ser utilizada. Ou seja, o código do exemplo se aplica tanto a VCL (Windows 32/64), bem como ao FireMonkey (Windows, OS X, iOS e Android)!

Uma vez criada sua aplicação cliente, você deve utilizar o wizard "DataSnap REST Client Module" para gerar o código do proxy que conterá as chamadas para sua aplicação servidora. Em outras palavras, você cria uma aplicação na plataforma desejada (desktop ou mobile) e utiliza o wizard acima para gerar o código necessário para conectá-la a aplicação servidora.

Estamos utilizando Visual LiveBindings para efetuar a ligação dos controles visuais. Por esta razão é necessário definir os fields dos FDMemTables para então fazer a ligação em tempo de design. Neste caso, o tipo de dado dos campos não é importante, mas o nome deve ser exatamente o mesmo retornado pelo servidor.

Vamos entender agora como fazer a chamada para a aplicação servidora, abaixo temos o código que retorna a lista de departamentos e preenche o TListView "ListViewDepartments":

procedure TDepartmentsClientForm.ButtonDepartmentsClick(Sender: TObject);
begin
  GetDepartmentNames;
end;
procedure TDepartmentsClientForm.GetDepartmentNames;
var
  LDataSetList: TFDJSONDataSets;
begin
  try
    LDataSetList := ClientModule2.ServerMethods1Client.GetDepartmentNames();
    UpdateDepartmentNames(LDataSetList);
  except
    on E: TDSRestProtocolException do
      HandleRestException(ClientModule2.DSRestConnection1, 'Get Departments error', E)
    else
      raise;
  end;
end;
procedure TDepartmentsClientForm.UpdateDepartmentNames(const ADataSetList: TFDJSONDataSets);
begin
  FDMemTableDepartments.Active  := False;
  FDMemTableDepartments.AppendData(
    TFDJSONDataSetsReader.GetListValue(ADataSetList, 0));
end;

Como podem observar, o método "GetDepartmentNames" faz uma chamada ao servidor (através da classe proxy gerada pelo wizard "DataSnap REST Client Module") retornando um "TFDJSONDataSets", ou seja, uma lista de datasets em formato JSON. Resta então, utilizando a classe auxiliar "TFDJSONDataSetsReader", reverter o processo de serialização, adicionando o resultando em um FDMemTable. O TFDMemTable pode ser comparado a um TClientDataSet, isto é, um dataset em memória. Os dados armazenados em um TFDMemTable podem ser alterados, e retornados ao servidor para atualização no banco de dados, fazendo-se uma chamada ao método correspondente:

procedure TDepartmentsClientForm.ButtonApplyUpdatesClick(Sender: TObject);
begin
  ApplyUpdates;
end;

function TDepartmentsClientForm.GetDeltas: TFDJSONDeltas;
begin
  Result := TFDJSONDeltas.Create;
  TFDJSONDeltasWriter.ListAdd(Result, sEmployees, FDMemTableEmployee);
  TFDJSONDeltasWriter.ListAdd(Result, sDepartment, FDMemTableDepartment);
end;

procedure TDepartmentsClientForm.ApplyUpdates;
var
  LDeltaList: TFDJSONDeltas;
begin
  LDeltaList := GetDeltas;
  try
    ClientModule2.ServerMethods1Client.ApplyChangesDepartmentEmployees(LDeltaList);
  except
    on E: TDSRestProtocolException do
      HandleRestException(ClientModule2.DSRestConnection1, 'Apply Updates error', E)
    else
      raise;
  end;
end;

Otimizando a Transferência dos Dados

Para aplicações onde todas as camadas (server e client) estão desenvolvidas em Delphi ou C++ Builder, podemos ainda aplicar uma compressão de dados para otimizar seu tempo de transferência. Obviamente, a diferença somente será perceptível em um ambiente com alguma restrição de banda (3G por exemplo).

Tanto o Delphi, quanto o C++ Builder, trazem uma implementação da ZLib, biblioteca para compressão de dados: http://docwiki.embarcadero.com/Libraries/XE6/en/System.ZLib. O mais interessante é que nossa implementação da ZLib está disponível para todas as plataformas suportadas, ou seja, você pode compactar uma informação em seu servidor Windows e descompactar em sua aplicação mobile iOS ou Android!

Você pode facilmente adicionar a compressão de dados em seus métodos JSON utilizando os "class methods" que estamos disponibilizando abaixo, os quais tornam o uso da ZLib bastante simples:

unit DSSupportClasses;

interface

uses System.Classes, System.ZLib, System.SysUtils;

type
  TDSSupportZLib = class(TObject)
  private
    { private declarations }
  protected
    { protected declarations }
  public
    { public declarations }
    class function ZCompressString(aText: string): TBytes;
    class function ZDecompressString(aText: TBytes): string;
  end;

implementation

{ TDSSupport }

class function TDSSupportZLib.ZCompressString(aText: string): TBytes;
var
  strInput: TBytesStream;
  strOutput: TBytesStream;
  Zipper: TZCompressionStream;
begin
  SetLength(Result, 0);
  strInput := TBytesStream.Create(TEncoding.UTF8.GetBytes(aText));
  strOutput := TBytesStream.Create;
  try
    Zipper := TZCompressionStream.Create(TCompressionLevel.clMax, strOutput);
    try
      Zipper.CopyFrom(strInput, strInput.size);
    finally
      Zipper.Free;
    end;
    Result := Copy(strOutput.Bytes, 0, strOutput.size);
  finally
    strInput.Free;
    strOutput.Free;
  end;
end;

class function TDSSupportZLib.ZDecompressString(aText: TBytes): string;
var
  strInput: TBytesStream;
  strOutput: TBytesStream;
  UnZipper: TZDecompressionStream;
begin
  Result := '';
  strInput := TBytesStream.Create(aText);
  strOutput := TBytesStream.Create;
  try
    UnZipper := TZDecompressionStream.Create(strInput);
    try
      try
        strOutput.CopyFrom(UnZipper, 0);
      except
        on E: Exception do
        begin
          raise Exception.Create('Error Message: ' + E.Message);
        end;
      end;
    finally
      UnZipper.Free;
    end;
    Result := TEncoding.UTF8.GetString(strOutput.Bytes, 0, strOutput.size);
  finally
    strInput.Free;
    strOutput.Free;
  end;
end;

end.

Porém, nenhuma implementação adicional será necessária em seu projeto. O que fizemos foi modificar a unit "Data.FireDACJSONReflect", onde estão implementadas as classes base do FireDAC JSON Reflection, adicionando a compressão/descompressão nos métodos de serialização JSON. Assim, basta adicionar esta versão da unit a seu projeto e fazer um "Build". Compressão/descompressão adicionadas!

Downloads e referências

EMBARCADERO CONFERENCE BRASIL!!!

Aproveitando a ocasião, já estamos preparando a conferência deste ano, e a página para submissão de palestras já está no ar! Se você tem algo interessante para mostrar, em Delphi e C++ Builder, ou ainda um caso de sucesso utilizando nossas ferramentas, estamos esperando por sua inscrição:

http://www.embarcaderoconference.com.br/palestrantes/

Tagged , , , ,

Update 1 para XE6 e outras novidades

O Update 1 para RAD Studio, Delphi e C++ Builder XE6 está disponível para usuários registrados. São mais de 120 correções e melhorias por todo o produto (30 deles registrados por usuários), reforçando nosso compromisso com a qualidade, performance e estabilidade da ferramenta.

Links para download

A lista de correções de problemas reportados por usuários pode ser encontrada neste link:

Notas relevantes

  • Observe que este update requer uma instalação completa do produto. O que você pode fazer é remover o produto preservando as configurações de instalação (registry settings), com isso todas as suas configurações - incluindo componentes de terceiros - serão preservadas. Importante: Remover o produto utilizando o procedimento de desinstalação padrão do Windows (pelo Painel de Controle) antes de iniciar com a nova instalação.
  • A IDE do RAD Studio, Delphi e C++ Builder apresenta um novo toolbar, onde é possível selecionar facilmente a plataforma (target platform) e também o device (target device), antes possível somente pelo project manager:

Buy One Tool, Get a Second Tool FREE!

Por um tempo limitado, a cada produto qualificado (RAD Studio, Delphi ou C++ Builder) que você compra, você pode escolher uma segunda ferramenta Embarcadero de valor igual ou menor - GRÁTIS! A oferta termina em 30 de junho de 2014!

Todos os detalhes aqui: https://www.embarcadero.com/br/bogo-info

Tagged , , ,

Fortes Report disponível para XE6

O FortesReport (não confundir com FastReport, nativo do Delphi, C++ Builder e RAD Studio) é um gerador de relatórios nacional, Open Source, produzido pela Fortes Informática de Fortaleza, exclusivamente para Delphi.

Em sua página oficial o download está homologado até a versão XE3 do Delphi. Porém, o usuário Willian Santos, da EdeSoft (parceiro de treinamentos da Embarcadero) atualizou o pacote para XE6 e os fontes estão disponíveis para download neste link:

http://goo.gl/xlBgCj

IMPORTANTE: O fabricante original da ferramenta, e também o autor desta adequação para Delphi XE6, estão isentos de qualquer responsabilidade e suporte sobre esta versão em particular.

Tagged , ,

Suporte para Acessibilidade no FireMonkey

Disponibilidade

O suporte de acessibilidade FireMonkey está disponível para Delphi e C++ Builder XE6 para Windows Win32, Win64 e para aplicações Mac OS-X. Os usuários registrados podem baixar o pacote neste link:

http://cc.embarcadero.com/item/29850

Tecnologia

O suporte de acessibilidade FireMonkey é baseado na interface Microsoft MSAA para Windows ( Microsoft Active Accessibility arquitetura ) e no protocolo de acessibilidade do OS-X e para MAC.

As informações sobre as APIs podem ser encontradas em :

MSAA: http://msdn.microsoft.com/en-us/library/ms971310.aspx

OS-X: http://goo.gl/dguz6N

A implementação do Windows MSAA foi testado com Freedom Scientific JAWS e Microsoft Windows Narrador.

No Mac OS X, ele foi testado contra os aplicativos da Apple VoiceOver .

Arquitetura

Para implementar as interfaces de acessibilidade do sistema operacional, uma nova classe de formulário foi derivado do padrão FireMonkey TForm. Esta nova classe (TAccForm) tem uma implementação diferente para o sistema Windows e outra para OS-X, mapeando todas as interações necessárias com os controles do FireMonkey. Esta classe TAccForm tem tratamento interno para os controles mais comuns e padrões do FireMonkey. Isso significa que, além de descender seus forms de TAccForm em vez de TForm, o desenvolvedor não tem medidas adicionais a tomar para permitir a acessibilidade em aplicações FireMonkey.

Implementação

Para ativar um formulário FireMonkey para acessibilidade, primeiro adicione as unidades necessárias que implementam esta característica. A acessibilidade vem em 3 unidades: FMX.ScreenReaderCommon, FMX.ScreenReader.Mac e FMX.ScreenReader.Win:

uses
  System.SysUtils, System.Types, System.UITypes, System.Rtti,
  System.Classes, System.Variants, FMX.Types, FMX.Controls, FMX.Forms,
  FMX.Dialogs, FMX.StdCtrls, FMX.ScreenReaderCommon
  {$IFDEF MACOS}
  , FMX.ScreenReader.Mac
  {$ELSE}
  , FMX.ScreenReader.Win
  {$ENDIF}
  ;

Em seguida, descenda seu form de TAccForm, em vez de TForm:

type
  TForm1 = class(TAccForm)
    procedure FormCreate(Sender: TObject);
  private
    { Private
declarations }
  public
    { Public
declarations }
  end;

var
  Form1: TForm1;

Controles Suportados

A implementação de acessibilidade FireMonkey tem suporte automático para os seguintes controles do FireMonkey :

TButton
TSpeedButton
TTracker
TEdit
TListBox
TComboBox
TComboEdit
TSpinBox
TLabel
TCheckBox
TRadioButton
TMainMenu
TMemo
TTreeView
TCustomGrid
Isso significa que quando você usar qualquer um desses controles em seu aplicativo, não há medidas adicionais a tomar. O TAccForm vai corretamente permitir ao software leitor de tela "ler" o texto ou o "estado" destes controles. Note-se também que todos os controles descendentes também irão herdar automaticamente o suporte de acessibilidade .

Controles Personalizados

Para adicionar suporte para um controle personalizado para acessibilidade, adicione a interface IFMXAccessibility em seu controle ao implementá-lo.

O IFMXAccessibility é definida como :

  // Interface for custom controls to add accessibility support
  IFMXAccessibility = interface
  ['{49AF90E5-341A-4869-9D3E-F659670FB4D8}']
    // Return the text to read by the accessibility interface
    function GetControlText: string;
    // Returns the accesibility role of the custom control
    function GetRole: TFMXRole;
  end;

Portanto, esta interface é constituída por dois métodos simples :

GetRole: returns the role of the custom control
GetControlText: returns the text the screenreader should voice when the control has focus

Já o tipo TFMXRole é definida como :

TFMXRole = (rStaticText, rCell, RTEXT, rButton, rCheckBox, rRadioButton, rGrid, rList, rSlider, rComboBox, rTabGroup);

Assim, para um controle de edição personalizada, este pode ser implementado como :

type

  TMyOwnFireMonkeyEdit = class(TControl, IFMXAccessibility)
  protected
    function GetControlText: string;
    function GetRole: TFMXRole;
  end;

implementation

{ TMyOwnFireMonkeyEdit }

function TMyOwnFireMonkeyEdit.GetControlText: string;
begin
  Result := GetMyControlText,
end;

function TMyOwnFireMonkeyEdit.GetRole: TFMXRole;
begin
  Result := rText;
end;

Tagged , , ,

Hotfix 1 for RAD Studio, Delphi, C++ Builder XE6

Este Hotfix disponibiliza alguns arquivos ausentes na release final do RAD Studio XE6, além de resolver um par de questões críticas para alguns desenvolvedores (dependendo da região e plataforma que você está utilizando).

A correção está disponível para usuários registrados em http://cc.embarcadero.com/Item/29847.

As questões resolvidas são:

- Corrige um problema com o IME (Input Method) para iOS, relacionado apenas com idiomas asiáticos;

- Alguns arquivos de cabeçalho faltantes relacionados com Tethering e DBX específicos para C++;

- Alguns arquivos de distribuição da biblioteca REST (para todas plataformas);

- Arquivos atualizados de alguns temas da VCL;

Portanto talvez você não precise deste hotfix em seus projetos, mas considerando o tempo para baixar e instalar (apenas 65MB), vale a pena garantir seu ambiente de desenvolvimento 100% atualizado.

Se você é um novo usuário, ou usuário de versões anteriores, você pode baixar o produto neste link para testá-lo por 30 dias (sem nenhuma restrição de funcionalidade):

http://www.embarcadero.com/downloads

E finalmente, neste link você encontra uma biblioteca de vídeos para iniciar com o desenvolvimento multi-device com RAD Studio (iOS, Android, OS X e Windows 32/64 bit):

http://www.embarcadero.com/products/rad-studio/product-demos.

Tagged , , ,

Delphi Tour 2014: Participe!

Você está convidado a conhecer de perto todas as novidades do RAD Studio XE6 (Delphi, C++ Builder e HTML5 Builder) durante o Delphi Tour 2014!

Razões para participar? Vou citar apenas algumas!

Você sabia que…

… seus aplicativos VCL serão capazes de acessar sensores,  utilizar novos componentes e funcionalidades como o Visual LiveBindings, e ainda novos estilos da VCL?

… você pode criar aplicações móveis complementares, e aplicativos de controle remoto, que se conectam com seus aplicativos de desktop VCL, via novos componentes para Tethering?

… você pode monetizar seus aplicativos móveis com o novo suporte para a compra de aplicativos e de publicidade no ​​iOS e Android?

… você pode usar a nova integração de serviços em nuvem para incorporar as notificações push, o armazenamento de arquivos em nuvem e a funcionalidade de gerenciamento de usuários em seus aplicativos via BaaS (Backend as a Service), utilizando os provedores mais populares do mercado?

… agora você conta com recursos exclusivos em C++, incluindo a capacidade de criar aplicações Android e iOS a partir de um único projeto, e suporte para pacotes de 64 bits para Windows?

Entusiasmado tanto quanto eu? Então não deixe para depois, pois as vagas são limitadas. Faça já sua inscrição para a cidade mais próxima!

http://www.embarcaderobr.com.br/tour/

Aguardamos sua presença!

Tagged , , , , ,

Hotfix 6 para RAD Studio, Delphi, C++Builder XE5 Atualizado!

Recentemente liberamos o HotFix 6 para RAD Studio, Delphi, C++Builder XE5, devido a mudanças de interface feitas pela Apple no iOS SDK 7.1 e Xcode 5.1.

O Hotfix resolveu o problema no OS X Mavericks (10.9), mas não para Mountain Lion (10.8). Por esta razão, no dia 17 de Abril último foi liberada uma nova versão deste Hotfix dando cobertura também ao Mountain Lion.

Aproveito aqui para listar todos os updates do XE5 que você NÃO deve deixar de instalar:

Tagged , , , ,

Lanzamiento Oficial del RAD Studio XE6!

RAD Studio XE6 acaba de llegar. Es la consolidación de la estrategia multi-dispositivos de Embarcadero, ya que en esta versión estamos trayendo el compilador C++ para Android. Así, el RAD compilará para Windows 32/64 bits, OS X, iOS y Android, tanto en Object Pascal como en C++. De esta manera usted puede elegir el lenguaje que más le guste, las características son 100% iguales para ambos lenguajes en todas las plataformas soportadas.

Novedades Principales

Hay muchas nuevas características en esta versión, la primera de las cuales ya hemos citado anteriormente, el compilador de C++ para Android. Vamos a explorar un poco más todo lo que es nuevo para la VCL, FireMonkey Desktop y FireMonkey Mobile.

1.- VCL

La VCL ha recibido importantes mejoras en el rendimiento y la estabilidad, está optimizado para Windows 7 y 8.1 (recuerde que debe migrar las aplicaciones que se ejecutan en Windows XP debido a la interrupción del soporte por parte de Microsoft), migración simplificada a FireDAC desde BDE y otros frameworks, además de nuevos componentes y funciones, tales como el soporte "full" de los estilos (incluidos los menús y los bordes), Taskbar Preview (Win7 y Win8), sensores para GPS y acelerómetros para la tableta de Windows,Tethering App for VCL (hablaremos más sobre en este post) y la Integración Service Cloud (BAAS) (más detalles a continuación)!

2.- FireMonkey

FireMonkey es quizás la zona donde se ha realizado el mayor número de optimizaciones, tenemos nuevos componentes, una Grid totalmente reformada, ListView con nuevas características visuales, WebBrowser con nuevos métodos y con carga de archivos locales, la plantilla y el soporte oficial de Google Glass, y el nuevo framework que harán de su aplicación móvil muy profesional, como el soporte para In App Purchasing y Advertising, tanto para iOS como para Android, con el mismo componente y código fuente (¡aquellos que ya la han desarrollado en cualquier otro entorno de desarrollo saben cuán duro es el trabajo!).

3.- App Tethering para VCL y FireMonkey

La función de Tethering permite que dos aplicaciones, incluso en diferentes plataformas (VCL o FireMonkey), ejecutadas en Windows, OSX, iOS o Android, intercambien datos directamente, sin ninguna aplicación de servidor en el medio. Esto significa que puede tomar partes de su aplicación VCL de escritorio actual (por ejemplo) y llevarlos al mundo de los móviles, y permitir que estas partes intercambien datos y realizen directamente las acciones. ¿No es increíble? Esta función está disponible para las aplicaciones en una misma red (WiFi en esta versión).

4.- Cloud Service (BaaS) Integration

Tanto Delphi XE6, como C++ Builder XE6, trae soporte completo para el Baas (Backend as a Service). Si esto es un tema nuevo para ti, recomendamos estos sitios: http://www.kinvey.com y https://parse.com. El Baas presenta una plataforma común para el intercambio y el almacenamiento de datos, y estos son dos de los principales proveedores en el mercado. En el futuro se añadirán otros proveedores.

Con este soporte, se pueden almacenar y recuperar datos directamente desde estos proveedores de servicios sin la necesidad de construir su propio servidor o incluso una capa intermedia, o la creación de una base de datos en la nube. Sólo suscríbete al servicio! Este soporte también está disponible para VCL, por lo que puede enviar datos desde una aplicación móvil, y luego procesarlas en el servidor de aplicaciones o de escritorio, sólo para nombrar una de las posibilidades.

Esta integración también proporciona soporte para "Push Notifications", lo que abre un gran gama de posibilidades para su aplicación móvil.

5.- In app purchasing y advertising

A través de este framework (TBannerAd y TInAppPurchase) puede agregar fácilmente a través de un solo componente para Android y iOS, el soporte a versiones de demostración y de pago de su aplicación, directamente integrado a tiendas virtuales como AppStoreGooglePlay. También le permite añadir y vender publicidad directamente en su aplicación, en ambas plataformas, y de manera unificada.

Observe en la imagen inferior el anuncio que se muestra en la aplicación Delphi.

Versión de prueba, Licencias y Bonus Pack

Recomiendo a todos descargar la nueva versión y probarlo, en realidad es una release muy estable y rico en características. Puede obtener la versión de prueba (que es 100% funcional durante el período de evaluación) en este enlace:

https://downloads.embarcadero.com/free/rad-studio.

Junto al XE6 estamos lanzando un nuevo tipo de actualización para los usuarios de la última versión, denominada Recharge Plan. Es decir, si usted es un usuario de la versión XE5, el precio de upgrade se reduce en gran medida, lo que le permite mantenerse al día!

Durante el lanzamiento se ofrecerá un Bonus Pack, que consiste en:

- TMS Modern Windows UI Pack

- VCL Premium Style Pack

- FireMonkey Premium Style Pack

Conclusiones

Bueno, esto es todo por un primer post sobre RAD Studio XE6Del mismo modo que empezamos este artículo, con esta versión se completa la estrategia multi-dispositivo de Embarcadero, con el desarrollo multiplataforma realmente nativo, proporcionando una alta productividad y rendimiento a través de Object Pascal o C++, todo ello integrado en un único entorno de desarrollo.

Tagged , , , , ,

Lançamento Oficial do RAD Studio XE6!

O RAD Studio XE6 acaba de chegar. Trata-se da consolidação da estratégia multi-device da Embarcadero, já que nesta versão estamos trazendo o compilador C++ para Android. Com isso o RAD passa a compilar para Windows 32/64 bit, OS X, iOS e Android, tanto em Object Pascal quanto em C++. Desta maneira você pode escolher a linguagem que mais lhe agrada, as features são 100% as mesmas para ambas as linguagens em todas as plataformas suportadas.

Principais Novidades

São muitas as novidades desta versão, a primeira delas já citamos acima, o compilador C++ para Android. Vamos explorar um pouco mais tudo o que há de novo para VCL, FireMonkey Desktop e FireMonkey Mobile.

1.- VCL

A VCL recebeu significativas melhorias de performance e estabilidade, suporte otimizado para Windows 7 e 8.1 (lembre-se que você deve migrar suas aplicações que hoje executam sob Windows XP dada a descontinuidade do suporte por parte da MS), migração simplificada para FireDAC a partir de BDE e outros frameworks, além de novos componentes e funcionalidades como suporte "full" a estilos (incluindo menus e bordas), Taskbar Preview (Win7 e Win8), Sensores para GPS e Accelerometers para tablets Windows, App Tethering para VCL (vamos falar mais sobre ainda neste post) e Cloud Service (BaaS) Integration (mais detalhes abaixo também)!

2.- FireMonkey

O FireMonkey talvez seja a área onde o maior número de otimizações foram realizadas, temos novos componentes, um Grid totalmente remodelado, ListView com novas funcionalidades visuais, WebBrowser com novos métodos e carregamento local de arquivos, suporte oficial e template para Google Glass, e novos frameworks que vão tornar sua aplicação mobile extremamente profissional, como o suporte a In App Purchasing e Advertising, tanto para iOS quanto Android com o mesmo componente e código fonte (quem já desenvolveu isso em qualquer outro ambiente sabe o quanto é trabalhoso)!

3.- App Tethering para VCL e FireMonkey

O recurso de Tethering permite que duas aplicações, mesmo em plataformas distintas (VCL ou FireMonkey), rodando em Windows, OSX, iOS ou Android, troquem dados de maneira direta, sem uma aplicação servidora intermediária. Isto significa que você pode tomar partes de sua atual aplicação desktop em VCL (por exemplo) e levá-las para o mundo mobile, e permitir que estas partes executem ações e troquem dados diretamente. Não é incrível? Este recurso está disponível para aplicações em uma mesma rede (WiFi nesta versão).

4.- Cloud Service (BaaS) Integration

Tanto o Delphi XE6, quanto o C++ Builder XE6, trazem suporte completo para os chamados BaaS (Backend as a Service). Se este é um assunto novo para você, recomendo fortemente conhecer estes sites: http://www.kinvey.com/https://parse.com/. O BaaS apresenta uma plataforma comum para troca e armazenamento de dados, e estes são dois dos principais provedores do mercado. No futuro outros providers serão adicionados.

Com este suporte, você pode armazenar e recuperar dados diretamente destes provedores de serviços, sem a necessidade de construir seu próprio servidor ou mesmo uma camada intermediária, ou ainda configurar um banco de dados nas nuvens. Basta assinar o serviço! Este suporte também está disponível para VCL, portanto você pode enviar dados a partir de uma app mobile e depois processá-los em sua aplicação servidora ou desktop, apenas para citar uma das possibilidades.

Esta integração também proporciona suporte a "Push Notifications", o que abre um leque gigantesco de possibilidades para sua aplicação mobile.

5.- In app purchasing e advertising

Através deste framework (TBannerAd e TInAppPurchase) você pode adicionar facilmente, através de um único componente para Android e iOS, suporte a versões de demonstração e pagas de sua aplicação, diretamente integradas as lojas virtuais como AppStore ou GooglePlay. Também permite adicionar e vender publicidade diretamente em sua app, nas duas plataformas, de maneira unificada.

Observe na imagem abaixo o banner sendo exibido na aplicação Delphi.

Recursos Adicionais

Estas são as grandes adições ao produto na versão XE6, mas existe muito mais a explorar. Temos avanços significativos no DataSnap, temos o FireDAC integrado ao DataSnap com suporte total a JSON, tanto no lado "server" quanto "client", novidades no gerenciamento de TFields/TDataSet, e muito mais. Vamos explorar cada um dos recursos em posts futuros.

Nesta página você encontra alguns vídeos sobre o produto e suas principais novidades: http://www.embarcadero.com/products/rad-studio/product-demos.

Versão Trial, Licenças e Bônus Pack

Convido a todos a baixar o trial e experimentar, realmente trata-se de uma release extremamente estável e muito rica em features. Você pode obter a versão trial (ela é 100% funcional durante o período de avaliação) neste link:

https://downloads.embarcadero.com/free/rad-studio.

Em conjunto com o XE6 estamos lançando também uma nova modalidade de upgrade para usuários da última versão, chamado de Recharge Plan. Ou seja, se você é usuário da versão XE5, seu valor de upgrade será bastante reduzido, facilitando o acesso a ferramenta e permitindo-lhe estar sempre atualizado!

Durante o lançamento será oferecido um Bônus Pack, o qual é composto de:

- TMS Modern Windows UI Pack

- VCL Premium Style Pack

- FireMonkey Premium Style Pack

Conclusão

Bem, isto é tudo para um primeiro post sobre o RAD Studio XE6. Conforme iniciamos este artigo, esta release completa a estratégia multi-device da Embarcadero, com desenvolvimento realmente nativo multiplataforma, provendo alta produtividade e performance, através de Object Pascal ou C++, tudo integrado em um ambiente de desenvolvimento único.

Tagged , , , , ,

Acessando classes Java e Objective-C com Delphi XE5

Olá pessoal,

Hoje vamos falar um pouco sobre acesso a classes nativas Java e Objective-C em Delphi XE5 para aplicações mobile.

Introdução

A ampla maioria das funcionalidades (visuais e não visuais) necessárias a uma aplicação mobile em Delphi ou C++ Builder estão representadas através de componentes e classes do FireMonkey e da RTL.

Porém, existem SDKs e bibliotecas específicas as quais não possuem sua representação no framework. Na maioria dos casos são na verdade classes e métodos que executam uma função específica daquele sistema operacional (iOS ou Android), ou ainda acessar um pacote de terceiros, como leitores de códigos de barra, apenas para citar um exemplo.

A boa notícia é que o Firemonkey é totalmente aberto para integrações, então vamos mostrar alguns exemplos do que pode ser feito.

Criando "Wrappers"

Os wrappers são a maneira de incorporar uma classe Java ou Objective-C em um projeto Delphi ou C++ Builder. Como referência, considere os links abaixo, um sobre Java e outro sobre iOS:

http://www.pclviewer.com/android/androidJNI.html

http://blogs.embarcadero.com/fernandorizzato/index.php/2013/06/26/codigo-de-barras-no-delphi-para-ios/

Alguns exemplos

Através de exemplos postados em blogs e portais, e também criando alguns outros, centralizamos em uma única app alguns wrappers que me chamaram a atenção, organizando seu código de maneira a tornar o entendimento o mais simples possível. O exemplo disponibilizado contempla:

- Abertura de URLs e execução de outras ações pré-definidas

- Status da rede, internet, 3G, etc.

- Envio de e-mail

- Leitura de código de barras (iOS e Android)

- Toast Message (exclusivo do Android)

Código Fonte

Vou postar abaixo, a título de ilustração, a unit responsável por obter o status de rede, porém você pode baixar o projeto completo neste link: http://cc.embarcadero.com/item/29811

unit NetworkState;
interface
uses
{$IFDEF IOS}
  Macapi.ObjectiveC, Macapi.CoreFoundation, Macapi.Dispatch,
  iOSApi.CocoaTypes, iOSApi.Foundation, Posix.SysSocket;
{$ENDIF}
{$IFDEF ANDROID}
System.SysUtils, FMX.Helpers.Android, Androidapi.JNIBridge,
  Androidapi.JNI.GraphicsContentViewText, Androidapi.JNI.JavaTypes;
{$ENDIF}
{$IFDEF IOS}
const
  libSystemConfiguration =
    '/System/Library/Frameworks/SystemConfiguration.framework/SystemConfiguration';
  kSCNetworkFlagsConnectionAutomatic = 8;
  kSCNetworkFlagsConnectionRequired = 4;
  kSCNetworkFlagsInterventionRequired = 16;
  kSCNetworkFlagsIsDirect = 131072;
  kSCNetworkFlagsIsLocalAddress = 65536;
  kSCNetworkFlagsReachable = 2;
  kSCNetworkFlagsTransientConnection = 1;
  kSCNetworkReachabilityFlagsConnectionAutomatic = 8;
  kSCNetworkReachabilityFlagsConnectionOnDemand = 32;
  kSCNetworkReachabilityFlagsConnectionOnTraffic = 8;
  kSCNetworkReachabilityFlagsConnectionRequired = 4;
  kSCNetworkReachabilityFlagsInterventionRequired = 16;
  kSCNetworkReachabilityFlagsIsDirect = 131072;
  kSCNetworkReachabilityFlagsIsLocalAddress = 65536;
  kSCNetworkReachabilityFlagsReachable = 2;
  kSCNetworkReachabilityFlagsTransientConnection = 1;
  kSCNetworkReachabilityFlagsIsWWAN = $40000;
{$ENDIF}
type
{$IFDEF IOS}
  SCNetworkReachabilityFlags = UInt32;
  SCNetworkReachabilityRef = ^__SCNetworkReachability;
  __SCNetworkReachability = record
  end;
  SCNetworkReachabilityContext = record
    version: CFIndex;
    info: Pointer;
    retain: function(info: Pointer): Pointer;
    release: procedure(info: Pointer);
    copyDescription: function(info: Pointer): CFStringRef;
  end;
  SCNetworkReachabilityContextPtr = ^SCNetworkReachabilityContext;
  SCNetworkReachabilityCallback = procedure(target: SCNetworkReachabilityRef;
    flags: SCNetworkReachabilityFlags; info: Pointer);
  TReachability = class;
  Reachability = interface(NSObject)
    ['{B405394F-57B1-4FF1-83D9-8FBFA38FFD7B}']
    function startNotifier: LongBool; cdecl;
    procedure stopNotifier; cdecl;
    function isReachable: LongBool; cdecl;
    function isReachableViaWWAN: LongBool; cdecl;
    function isReachableViaWiFi: LongBool; cdecl;
    function isConnectionRequired: LongBool; cdecl;
    function connectionRequired: LongBool; cdecl;
    function isConnectionOnDemand: LongBool; cdecl;
    function isInterventionRequired: LongBool; cdecl;
    function currentReachabilityStatus: NSInteger; cdecl;
    function reachabilityFlags: SCNetworkReachabilityFlags; cdecl;
    function currentReachabilityString: NSString; cdecl;
    function currentReachabilityFlags: NSString; cdecl;
  end;
  ReachabilityClass = interface(NSObjectClass)
    ['{39EC0490-2787-4BB9-95EA-77BB885BFD01}']
    function reachabilityWithHostname(hostname: NSString): Pointer; cdecl;
    function reachabilityForInternetConnection: Pointer; cdecl;
    function reachabilityWithAddress: Pointer; cdecl;
    function reachabilityForLocalWiFi: Pointer; cdecl;
  end;
  TReachability = class(TOCGenericImport<ReachabilityClass, Reachability>)
  end;
function SCNetworkReachabilityCreateWithAddress(allocator: CFAllocatorRef;
  address: psockaddr): SCNetworkReachabilityRef; cdecl;
  external libSystemConfiguration name _PU +
  'SCNetworkReachabilityCreateWithAddress';
function SCNetworkReachabilityCreateWithAddressPair(allocator: CFAllocatorRef;
  localAddress: psockaddr; remoteAddress: psockaddr): SCNetworkReachabilityRef;
  cdecl; external libSystemConfiguration name _PU +
  'SCNetworkReachabilityCreateWithAddressPair';
function SCNetworkReachabilityCreateWithName(allocator: CFAllocatorRef;
  nodename: PChar): SCNetworkReachabilityRef; cdecl;
  external libSystemConfiguration name _PU +
  'SCNetworkReachabilityCreateWithName';
function SCNetworkReachabilityGetTypeID: CFTypeID; cdecl;
  external libSystemConfiguration name _PU + 'SCNetworkReachabilityGetTypeID';
function SCNetworkReachabilityGetFlags(target: SCNetworkReachabilityRef;
  var flags: SCNetworkReachabilityFlags): Boolean; cdecl;
  external libSystemConfiguration name _PU + 'SCNetworkReachabilityGetFlags';
function SCNetworkReachabilitySetCallback(target: SCNetworkReachabilityRef;
  callout: SCNetworkReachabilityCallback;
  var context: SCNetworkReachabilityContext): Boolean; cdecl;
  external libSystemConfiguration name _PU + 'SCNetworkReachabilitySetCallback';
function SCNetworkReachabilityScheduleWithRunLoop
  (target: SCNetworkReachabilityRef; runLoop: CFRunLoopRef;
  runLoopMode: CFStringRef): Boolean; cdecl;
  external libSystemConfiguration name _PU +
  'SCNetworkReachabilityScheduleWithRunLoop';
function SCNetworkReachabilityUnscheduleFromRunLoop
  (target: SCNetworkReachabilityRef; runLoop: CFRunLoopRef;
  runLoopMode: CFStringRef): Boolean; cdecl;
  external libSystemConfiguration name _PU +
  'SCNetworkReachabilityUnscheduleFromRunLoop';
function SCNetworkReachabilitySetDispatchQueue(target: SCNetworkReachabilityRef;
  queue: dispatch_queue_t): Boolean; cdecl;
  external libSystemConfiguration name _PU +
  'SCNetworkReachabilitySetDispatchQueue';
{$IFDEF CPUARM}
function FakeLoader: Reachability; cdecl;
  external 'libReachability.a' name 'OBJC_CLASS_$_Reachability';
{$ENDIF}
{$ENDIF}
{$IFDEF ANDROID}
JConnectivityManager = interface;
JNetworkInfo = interface;
JNetworkInfoClass = interface(JObjectClass)
  ['{E92E86E8-0BDE-4D5F-B44E-3148BD63A14C}']
end;
[JavaSignature('android/net/NetworkInfo')]
JNetworkInfo = interface(JObject)['{6DF61A40-8D17-4E51-8EF2-32CDC81AC372}']
{ Methods }
function isAvailable: Boolean;
cdecl;
function isConnected: Boolean; cdecl;
  function isConnectedOrConnecting: Boolean; cdecl;
  end;
TJNetworkInfo = class(TJavaGenericImport<JNetworkInfoClass, JNetworkInfo>)
end;
JConnectivityManagerClass = interface(JObjectClass)
  ['{E03A261F-59A4-4236-8CDF-0068FC6C5FA1}']
{ Property methods }
function _GetTYPE_WIFI: Integer;
cdecl;
function _GetTYPE_WIMAX: Integer; cdecl;
  function _GetTYPE_MOBILE: Integer; cdecl;
  { Properties }
  property TYPE_WIFI: Integer read _GetTYPE_WIFI;
  property TYPE_WIMAX: Integer read _GetTYPE_WIMAX;
  property TYPE_MOBILE: Integer read _GetTYPE_MOBILE;
  end;
[JavaSignature('android/net/ConnectivityManager')]
JConnectivityManager = interface(JObject)
  ['{1C4C1873-65AE-4722-8EEF-36BBF423C9C5}']
{ Methods }
function getActiveNetworkInfo: JNetworkInfo;
cdecl;
function getNetworkInfo(networkType: Integer): JNetworkInfo; cdecl;
end;
TJConnectivityManager = class(TJavaGenericImport<JConnectivityManagerClass,
  JConnectivityManager>)
end;
{$ENDIF}
type
  TMobileNetworkStatus = class(TObject)
  public
    constructor Create;
    destructor Destroy; override;
    function isConnected: Boolean;
    function IsWiFiConnected: Boolean;
    function IsMobileConnected: Boolean;
  end;
implementation
{$IFDEF ANDROID}
function GetConnectivityManager: JConnectivityManager;
var
  ConnectivityServiceNative: JObject;
begin
  ConnectivityServiceNative := SharedActivityContext.getSystemService
    (TJContext.JavaClass.CONNECTIVITY_SERVICE);
  if not Assigned(ConnectivityServiceNative) then
    raise Exception.Create('Could not locate Connectivity Service');
  Result := TJConnectivityManager.Wrap
    ((ConnectivityServiceNative as ILocalObject).GetObjectID);
  if not Assigned(Result) then
    raise Exception.Create('Could not access Connectivity Manager');
end;
{$ENDIF}
{$IFDEF IOS}
function GetInternetReachability: Reachability;
begin
  Result := TReachability.Wrap
    (TReachability.OCClass.reachabilityForInternetConnection);
end;
{$ENDIF}
constructor TMobileNetworkStatus.Create;
begin
end;
destructor TMobileNetworkStatus.Destroy;
begin
  inherited;
end;
function TMobileNetworkStatus.isConnected: Boolean;
{$IFDEF ANDROID}
var
  ConnectivityManager: JConnectivityManager;
  ActiveNetwork: JNetworkInfo;
{$ENDIF}
begin
{$IFDEF IOS}
  Result := GetInternetReachability.isReachable;
{$ENDIF}
{$IFDEF ANDROID}
  ConnectivityManager := GetConnectivityManager;
  ActiveNetwork := ConnectivityManager.getActiveNetworkInfo;
  Result := Assigned(ActiveNetwork) and ActiveNetwork.isConnected;
{$ENDIF}
end;
function TMobileNetworkStatus.IsMobileConnected: Boolean;
{$IFDEF ANDROID}
var
  ConnectivityManager: JConnectivityManager;
  MobileNetwork: JNetworkInfo;
{$ENDIF}
begin
{$IFDEF IOS}
  Result := GetInternetReachability.isReachableViaWWAN;
{$ENDIF}
{$IFDEF ANDROID}
  ConnectivityManager := GetConnectivityManager;
  MobileNetwork := ConnectivityManager.getNetworkInfo
    (TJConnectivityManager.JavaClass.TYPE_MOBILE);
  Result := MobileNetwork.isConnected;
{$ENDIF}
end;
function TMobileNetworkStatus.IsWiFiConnected: Boolean;
{$IFDEF ANDROID}
var
  ConnectivityManager: JConnectivityManager;
  WiFiNetwork: JNetworkInfo;
{$ENDIF}
begin
{$IFDEF IOS}
  Result := GetInternetReachability.isReachableViaWiFi;
{$ENDIF}
{$IFDEF ANDROID}
  ConnectivityManager := GetConnectivityManager;
  WiFiNetwork := ConnectivityManager.getNetworkInfo
    (TJConnectivityManager.JavaClass.TYPE_WIFI);
  Result := WiFiNetwork.isConnected;
{$ENDIF}
end;
initialization
{$IFDEF IOS}
{$IFDEF CPUARM}
if False then
  FakeLoader;
{$ENDIF}
{$ENDIF}
end.

Notas Importantes

1- No exemplo que faz acesso ao status da rede/internet/3G, quando utilizado para iOS, faz-se necessário importar o framework "SystemConfiguration" no SDK Manager do Delphi ou C++ Builder. Detalhes de como fazê-lo estão neste post: http://delphi.radsoft.com.au/2013/10/adding-other-ios-frameworks-to-the-sdk-manager/

2- A leitura de código de barras para iOS faz uso da biblioteca ZBar, já inclusa neste projeto. Maiores detalhes e novas versões, aqui: http://zbar.sourceforge.net/

3- A leitura de código de barras para Android faz uso do aplicativo Zebra Crossing: https://play.google.com/store/apps/details?id=com.google.zxing.client.android

Outras fontes de pesquisa

Provavelmente você deve estar se perguntando o que mais é possível fazer, então vou listar abaixo algumas URLs interessantes que servirão como ponto de partida:

https://www.embarcadero.com/rad-in-action/programming-devices-and-gadgets

http://blogs.embarcadero.com/davidi/2014/01/09/43215

http://www.fmxexpress.com/tag/sdk/

É isso aí… abraços e até o próximo!

Tagged , , ,

Bad Behavior has blocked 0 access attempts in the last 7 days.

Close