Skip to content

Commit

Permalink
Versão 1.0.2
Browse files Browse the repository at this point in the history
  • Loading branch information
FabricioMF100 committed Jul 27, 2019
1 parent 82cf343 commit 1433905
Show file tree
Hide file tree
Showing 41 changed files with 1,108 additions and 59 deletions.
3 changes: 2 additions & 1 deletion DelphiAutoUpdate/DelphiSelfUpdate.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
[App]
Versao=1.0.1
[Download]
Link=http://www.soachoaki.com.br/Content/download/DemoDelphiAutoUpdate.zip
Link=http://www.soachoaki.com.br/Content/download/DemoDelphiAutoUpdate.zip
MD5=3A381466CB0BB1E16CD5652EF8F7692E
130 changes: 103 additions & 27 deletions DelphiAutoUpdate/DelphiSelfUpdate/DelphiSelfUpdate.pas
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

{
SelfUpdate para Delphi - Escrito por Fabricio Marques
Versão: 1.0.1
Versão: 1.0.2
https://github.com/FabricioMF100/DelphiSelfUpdate
Expand Down Expand Up @@ -49,9 +49,11 @@ interface
uses
System.SysUtils, System.Types, System.Classes, System.IOUtils,
System.Net.HttpClient, System.Net.HttpClientComponent,
System.Permissions, System.Threading, System.IniFiles,
IdHashMessageDigest, System.IniFiles,
Fmx.Objects, Fmx.StdCtrls, Fmx.Forms, Fmx.Types, System.UiTypes,
FMX.DialogService, FMX.Dialogs,
{$IFDEF ANDROID}
System.Permissions,
Androidapi.Helpers,
Androidapi.JNI.GraphicsContentViewText,
FMX.Platform.Android,
Expand All @@ -61,7 +63,9 @@ interface
//Androidapi.JNI.App,
Androidapi.JNI.Support,
Androidapi.JNI.Os,
Androidapi.IOUtils;
Androidapi.IOUtils,
{$ENDIF}
System.Threading;

type
TSelfUpdateDelphiDownloading = class
Expand All @@ -87,19 +91,25 @@ TSelfUpdateDelphi = class
private
FormBase: TForm;
ErroDownload: boolean;
ChecagemMD5: String;
{ Private declarations }
procedure MensagemErro(StrMensagem: String);
function ChecarMD5(Stream: TStream; MD5: String): boolean;
procedure ObterPermissoes;
procedure ChamarInstalacao;
procedure NetHTTPClientOnReceiveData(const Sender: TObject; AContentLength: Int64; AReadCount: Int64; var Abort: Boolean);
procedure NetHTTPClientOnRequestError(const Sender: TObject; const AError: string);
function BaixarAtualizacao:boolean;
procedure ProcessarAtualizacao;
procedure DisplayRationale(const APermissions: TArray<string>; const APostRationaleProc: TProc);
{$IFDEF ANDROID}
procedure ResultadoPermissoes(const APermissions: TArray<string>; const AGrantResults: TArray<TPermissionStatus>);
{$ENDIF}
public
{ Public declarations }
VersaoAtualizacaoDisponivel: String;
class function ObterVersaoAtualApp:string;
procedure VerificarAtualizacaoEPerguntar(LinkInfoVersao, VersaoAtual: string);
procedure VerificarAtualizacaoEPerguntar(LinkInfoVersao, VersaoAtual: string; MostrarVersao: boolean);
function VerificarAtualizacao(LinkInfoVersao, VersaoAtual: string; var VLinkRetorno: string):boolean;
procedure Atualizar(UrlDownload, NomeDoArquivoSalvar: string);
constructor Create(AOwner: TForm);
Expand All @@ -113,7 +123,7 @@ procedure TSelfUpdateDelphi.Atualizar(UrlDownload, NomeDoArquivoSalvar: string);
begin
LinkDownload:= UrlDownload;
NomeArquivoApk:= NomeDoArquivoSalvar;

{$IFDEF ANDROID}
//Caso seja Android 6 ou superior solicita permissão
if TOSVersion.Major < 6 then
begin
Expand All @@ -124,6 +134,7 @@ procedure TSelfUpdateDelphi.Atualizar(UrlDownload, NomeDoArquivoSalvar: string);
//Caso seja Android 5 ou inferior a permissão já é concedida
ObterPermissoes;
end;
{$ENDIF}
end;

function TSelfUpdateDelphi.BaixarAtualizacao: boolean;
Expand All @@ -149,6 +160,23 @@ function TSelfUpdateDelphi.BaixarAtualizacao: boolean;
VHttp.Get(LinkDownload, VStreamArquivo);
finally
VHttp.Free;

//Checa a integridade caso a sequencia MD5 tenha sido fornecida
if String.IsNullOrEmpty(ChecagemMD5) = false then
begin
TThread.Synchronize(nil, procedure ()
begin
DialogoAndamento.PrgBAndamento.Value:= DialogoAndamento.PrgBAndamento.Max;
DialogoAndamento.TxtFazendoDownload.Text:= 'Download concluído';
DialogoAndamento.TxtAndamento.Text:= 'Verificando integridade do arquivo...';
end);
if ChecarMD5(VStreamArquivo, ChecagemMD5) = False then
begin
ErroDownload:= True;
MensagemErro('Ocorreu um problema no download e o arquivo baixado está corrompido ou inválido.' + sLineBreak + 'Deseja tentar novamente?');
end;
end;

VStreamArquivo.Free;

//Ao finalizar executa a instalação
Expand All @@ -160,7 +188,7 @@ function TSelfUpdateDelphi.BaixarAtualizacao: boolean;
DialogoAndamento.TxtFazendoDownload.Text:= 'Download concluído';
DialogoAndamento.TxtAndamento.Text:= 'A instalação será iniciada...';
end);
Sleep(1000);
Sleep(1500);
TThread.Synchronize(nil, procedure ()
begin
ChamarInstalacao;
Expand All @@ -170,12 +198,15 @@ function TSelfUpdateDelphi.BaixarAtualizacao: boolean;
end;

procedure TSelfUpdateDelphi.ChamarInstalacao;
{$IFDEF ANDROID}
var
VArquivo:Jfile;
Intent:JIntent;
VUriArquivo: Jnet_Uri;
VStrFileProvider: string;
{$ENDIF}
begin
{$IFDEF ANDROID}
VArquivo:=TJfile.JavaClass.init(StringToJstring(DiretorioDownload),StringToJstring(NomeArquivoApk));

if TOSVersion.Major < 7 then
Expand All @@ -201,14 +232,33 @@ procedure TSelfUpdateDelphi.ChamarInstalacao;
end;
Intent.setDataAndType(VUriArquivo,StringToJstring('application/vnd.android.package-archive'));
SharedActivityContext.startActivity(Intent);
{$ENDIF}
end;

function TSelfUpdateDelphi.ChecarMD5(Stream: TStream; MD5: String): boolean;
var
IdMD5: TIdHashMessageDigest5;
begin
//Faz a verificação de integridade do arquivo via MD5
IdMD5 := TIdHashMessageDigest5.Create;
Result:= False;
try
if IdMD5.HashStreamAsHex(Stream) = Md5 then
begin
Result := True;
end;
finally
IdMD5.Free;
end;
end;

constructor TSelfUpdateDelphi.Create(AOwner: TForm);
begin
FormBase:= AOwner;
//Diretório de download
{$IFDEF ANDROID}
DiretorioDownload:= GetSharedDownloadsDir;
{$ENDIF}
end;

procedure TSelfUpdateDelphi.DisplayRationale(const APermissions: TArray<string>; const APostRationaleProc: TProc);
Expand All @@ -221,20 +271,7 @@ procedure TSelfUpdateDelphi.DisplayRationale(const APermissions: TArray<string>;
end)
end;

procedure TSelfUpdateDelphi.NetHTTPClientOnReceiveData(const Sender: TObject;
AContentLength, AReadCount: Int64; var Abort: Boolean);
begin
//Atualização da porcentagem do download
TThread.Synchronize(nil, procedure ()
begin
DialogoAndamento.PrgBAndamento.Max:= AContentLength;
DialogoAndamento.PrgBAndamento.Value:= AReadCount;
DialogoAndamento.TxtAndamento.Text:= FloatToStr(Round((AReadCount / AContentLength) * 100)) + '% concluído';
end);
end;

procedure TSelfUpdateDelphi.NetHTTPClientOnRequestError(const Sender: TObject;
const AError: string);
procedure TSelfUpdateDelphi.MensagemErro(StrMensagem: String);
var
VMsg: TDialogService;
begin
Expand All @@ -244,7 +281,7 @@ procedure TSelfUpdateDelphi.NetHTTPClientOnRequestError(const Sender: TObject;
VMsg.PreferredMode:= TDialogService.TPreferredMode.Platform;
TThread.Synchronize(nil, procedure ()
begin
VMsg.MessageDialog('Houve um problema ao tentar concluir o download.' + sLineBreak + 'Deseja tentar novamente?' + sLineBreak + sLineBreak + 'Problema ocorrido: ' + AError, TMsgDlgType.mtConfirmation, FMX.Dialogs.mbYesNo, TMsgDlgBtn.mbYes, 0,
VMsg.MessageDialog(StrMensagem, TMsgDlgType.mtConfirmation, FMX.Dialogs.mbYesNo, TMsgDlgBtn.mbYes, 0,
procedure(const AResult: TModalResult)
begin
case AResult of
Expand All @@ -254,6 +291,26 @@ procedure TSelfUpdateDelphi.NetHTTPClientOnRequestError(const Sender: TObject;
end);
end;

procedure TSelfUpdateDelphi.NetHTTPClientOnReceiveData(const Sender: TObject;
AContentLength, AReadCount: Int64; var Abort: Boolean);
begin
//Atualização da porcentagem do download
TThread.Synchronize(nil, procedure ()
begin
DialogoAndamento.PrgBAndamento.Max:= AContentLength;
DialogoAndamento.PrgBAndamento.Value:= AReadCount;
DialogoAndamento.TxtAndamento.Text:= FloatToStr(Round((AReadCount / AContentLength) * 100)) + '% concluído';
end);
end;

procedure TSelfUpdateDelphi.NetHTTPClientOnRequestError(const Sender: TObject;
const AError: string);
begin
//Mostra um diálogo perguntando se deseja tentar novamente
MensagemErro('Houve um problema ao tentar concluir o download.' + sLineBreak + 'Deseja tentar novamente?' + sLineBreak + sLineBreak + 'Problema ocorrido: ' + AError);
end;

{$IFDEF ANDROID}
procedure TSelfUpdateDelphi.ResultadoPermissoes(const APermissions: TArray<string>; const AGrantResults: TArray<TPermissionStatus>);
begin
//Caso seja permitido executa a atualização
Expand All @@ -265,15 +322,17 @@ procedure TSelfUpdateDelphi.ResultadoPermissoes(const APermissions: TArray<strin
end;
end;
end;
{$ENDIF}

function TSelfUpdateDelphi.VerificarAtualizacao(
LinkInfoVersao, VersaoAtual: string; var VLinkRetorno: string): boolean;
var
VHttp: TNetHTTPClient;
VResponse: IHTTPResponse;
VIniResposta: TMemIniFile;
VStrVersao: String;
//VStrVersao: String;
begin
{$IFDEF ANDROID}
// Acessa o link e verifica as informações de versão
VHttp:= TNetHTTPClient.Create(nil);
try
Expand All @@ -287,15 +346,21 @@ function TSelfUpdateDelphi.VerificarAtualizacao(
begin
//Carrega as informações e checa se a versão é diferente
VIniResposta:= TMemIniFile.Create(VResponse.ContentStream);
VStrVersao:= VIniResposta.ReadString('App', 'Versao', '');
if (String.isNullOrEmpty(VStrVersao) = false) and (VStrVersao <> VersaoAtual) then
VersaoAtualizacaoDisponivel:= VIniResposta.ReadString('App', 'Versao', '');
if (String.isNullOrEmpty(VersaoAtualizacaoDisponivel) = false) and (VersaoAtualizacaoDisponivel <> VersaoAtual) then
begin
VLinkRetorno:= VIniResposta.ReadString('Download', 'Link', '');
Result:= True;
if VIniResposta.ValueExists('Download', 'MD5') then
begin
ChecagemMD5:= VIniResposta.ReadString('Download', 'MD5', '');
end;
end
else
begin
{$ENDIF}
Result:= False;
{$IFDEF ANDROID}
end;
VIniResposta.Free;
end;
Expand All @@ -305,21 +370,28 @@ function TSelfUpdateDelphi.VerificarAtualizacao(
VIniResposta.Free;
Result:= False;
end;

{$ENDIF}
end;

procedure TSelfUpdateDelphi.VerificarAtualizacaoEPerguntar(
LinkInfoVersao, VersaoAtual: string);
LinkInfoVersao, VersaoAtual: string; MostrarVersao: boolean);
var
VMsg: TDialogService;
VStrMensagem: String;
VLinkRetorno: string;
begin
//Mostra um diálogo perguntando se deseja atualizar caso haja atualização
if VerificarAtualizacao(LinkInfoVersao, VersaoAtual, VLinkRetorno) then
begin
VMsg:= TDialogService.Create;
VMsg.PreferredMode:= TDialogService.TPreferredMode.Sync;
VMsg.MessageDialog('Há uma atualização disponível para o app.' + sLineBreak + 'Deseja atualizar agora?', TMsgDlgType.mtConfirmation, FMX.Dialogs.mbYesNo, TMsgDlgBtn.mbYes, 0,

VStrMensagem:= 'Há uma atualização disponível para o app.' + sLineBreak + 'Deseja atualizar agora?';
if MostrarVersao then
begin
VStrMensagem:= VStrMensagem + sLineBreak + 'Versão instalada: ' + VersaoAtual + sLineBreak + 'Atualização disponível: ' + VersaoAtualizacaoDisponivel;
end;
VMsg.MessageDialog(VStrMensagem, TMsgDlgType.mtConfirmation, FMX.Dialogs.mbYesNo, TMsgDlgBtn.mbYes, 0,
procedure(const AResult: TModalResult)
begin
case AResult of
Expand All @@ -340,15 +412,19 @@ procedure TSelfUpdateDelphi.ObterPermissoes;
end;

class function TSelfUpdateDelphi.ObterVersaoAtualApp: string;
{$IFDEF ANDROID}
var
PackageManager: JPackageManager;
PackageInfo: JPackageInfo;
{$ENDIF}
begin
//Obtem a versão atual do app
{$IFDEF ANDROID}
PackageManager := SharedActivityContext.getPackageManager;
PackageInfo := PackageManager.getPackageInfo
(SharedActivityContext.getPackageName, 0);
result := JStringToString(PackageInfo.versionName);
{$ENDIF}
end;

procedure TSelfUpdateDelphi.ProcessarAtualizacao;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- BEGIN_INCLUDE(manifest) -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.embarcadero.DemoDelphiAutoUpdate"
android:versionCode="2"
android:versionName="1.0.1"
android:installLocation="auto">

<uses-sdk android:minSdkVersion="19" android:targetSdkVersion="28" />
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

<uses-feature android:glEsVersion="0x00020000" android:required="True"/>
<application android:persistent="False"
android:restoreAnyVersion="False"
android:label="DemoDelphiAutoUpdate"
android:debuggable="True"
android:largeHeap="False"
android:icon="@drawable/ic_launcher"
android:theme="@style/AppTheme"
android:hardwareAccelerated="true"
android:resizeableActivity="false"
android:usesCleartextTraffic="true">

<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.embarcadero.DemoDelphiAutoUpdate.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths" />
</provider>



<!-- Our activity is a subclass of the built-in NativeActivity framework class.
This will take care of integrating with our NDK code. -->
<activity android:name="com.embarcadero.firemonkey.FMXNativeActivity"
android:label="DemoDelphiAutoUpdate"
android:configChanges="orientation|keyboard|keyboardHidden|screenSize"
android:launchMode="singleTask">
<!-- Tell NativeActivity the name of our .so -->
<meta-data android:name="android.app.lib_name"
android:value="DemoDelphiAutoUpdate" />
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

<receiver android:name="com.embarcadero.rtl.notifications.NotificationAlarm" />

</application>
</manifest>
<!-- END_INCLUDE(manifest) -->
Loading

0 comments on commit 1433905

Please sign in to comment.