Taking pictures on Android from Delphi Firemonkey XE5 app - android

Has anyone been able to take pictures from camera on Android from within the app written in Delphi Firemonkey XE5? How about the video capture?
This is believed to be either a bug in a framework or just something with missing documentation about it.
Can anyone tell why the code bellow doesn't work / retrieve any image from a camera on Android?
Dropped a TCameraComponent on a form, and a TImage component as well, and nothing happens.
procedure TCameraComponentForm.OnCreate(Sender: TObject);
begin
CameraComponent1.Kind := FMX.Media.TCameraKind.ckFrontCamera;
CameraComponent1.FlashMode := FMX.Media.TFlashMode.fmFlashOff;
CameraComponent1.Active := True;
end;
procedure TCameraComponentForm.CameraComponent1SampleBufferReady(
Sender: TObject; const ATime: Int64);
begin
CameraComponent1.SampleBufferToBitmap(Image1.Bitmap, True);
Image1.Width := Image1.Bitmap.Width;
Image1.Height := Image1.Bitmap.Height;
end;
Permissions are set correctly.

This code works fine:
procedure TfrmPrincipal.SampleBufferSync;
begin
cmcPrincipal.SampleBufferToBitmap(imgFoto.Bitmap, true);
end;
procedure TfrmPrincipal.cmcPrincipalSampleBufferReady(Sender: TObject;
const ATime: Int64);
begin
TThread.Synchronize(TThread.CurrentThread, SampleBufferSync);
// CameraComponent1.SampleBufferToBitmap(imgFoto.Bitmap, True);
// imgFoto.Width := imgFoto.Bitmap.Width;
// imgFoto.Height := imgFoto.Bitmap.Height;
end;
procedure TfrmPrincipal.FormShow(Sender: TObject);
begin
cmcPrincipal.Kind := FMX.Media.TCameraKind.ckBackCamera;
try
cmcPrincipal.FlashMode := FMX.Media.TFlashMode.fmFlashOff;
except
end;
cmcPrincipal.Active := True;
end;

Related

how to configure tls on Delphi TRestClient component

Helo,
I typed the code as follows and this code works well.
By using an https connection I hope that the Packet Data received cannot be read by applications such as Wireshark or the Packet Capture application on Android.
how do you configure the client side?
this my code
procedure TForm1.Button1Click(Sender: TObject);
var
MyCompletionHandler: TCompletionHandler;
MyErrorCompletionHandler: TCompletionHandlerWithError;
begin
ShowLoadingIndicator(Self, True);
Memo1.Lines.Clear;
RESTClient1.BaseURL := 'https://reqres.in/';
RESTClient1.RaiseExceptionOn500 := False;
RESTClient1.SecureProtocols := [THTTPSecureProtocol.TLS12];
RESTRequest1.ClearBody;
RESTRequest1.Resource := 'api/users';
MyCompletionHandler := procedure
var i: Integer;
tJson: TJSONValue;
begin
Label1.Text := 'Complete!';
Memo1.Lines.Append('Header: ');
for I := 0 to RESTResponse1.Headers.Count-1 do
Memo1.Lines.Append(RESTResponse1.Headers.Strings[I]);
Memo1.Lines.Append('');
Memo1.Lines.Append('Body:');
tJson := TJSONObject.ParseJSONValue(RESTResponse1.Content);
try
memo1.Lines.Append(REST.Json.TJson.Format(tJson));
finally
FreeAndNil(tJson);
end;
HideLoadingIndicator(Self);
end;
MyErrorCompletionHandler := procedure(AObject: TObject)
begin
Label1.Text := 'Error!';
HideLoadingIndicator(Self);
end;
RESTRequest1.ExecuteAsync(MyCompletionHandler, True, True, MyErrorCompletionHandler);
end;
result packet capture using
app
and this simple apps made with firemonkey:
Simple Apps

Firemonkey blocking dialogs on Android

I am porting an older project (app for iOS ans Android) for a customer from an older AppMethod version to the newest RAD Studio version (10.0 Berlin). MessageDlg and similar were used often in the project but this does not work anymore. The apps shows a message, that modal dialogs are not supported on Android. I know and understand why this is so for the Android platform (so please don't mark this question as a dublicate by referencing to an explanation - I'm asking for something else!).
Firemonkey allows to set an anonymous function to be executed asynchronously after the user taps on a button in the dialog box or when it is closed. However, there is often code which depends on users decision or code which must be executed after the dialog box, regardless of which button the user taps on. For example, a dialog box must ask the user for his decision in the middle of an ongoing operation. Further operations then depend on the users decision (which might also include to stop further code execution in the current application!). Since RAD Studio does not support blocking dialogs on Android, I seem to be forced to break up my code - from one function to multiple functions (worse readability...). This gets even more complicated when there are nested function calls with possible modal dialog boxes, which require user interaction.
Is there still a way to emulate blocking dialogs somehow? It doesn't has to be perfect. I just don't want to rewrite a lot of code and outsource even small code fragments into many separate functions, everwhere where user interaction is required.
OK, I think the following "dirty" solution might be sufficient for me:
unit Unit1;
interface
uses
System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.DialogService,
FMX.Controls.Presentation, FMX.StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private-Deklarationen }
public
{ Public-Deklarationen }
end;
var
Form1: TForm1;
blockDlg: array[0..99] of Boolean;
blockDlgIdx: Integer = 0;
implementation
{$R *.fmx}
procedure NShowMessageAsync(AMessage: String);
begin
TDialogService.ShowMessage(AMessage);
end;
procedure NShowMessageSync(AMessage: String);
var
locBlockIdx: Integer;
begin
if blockDlgIdx = Length(blockDlg)-1 then blockDlgIdx := 0 else Inc(blockDlgIdx);
locBlockIdx := blockDlgIdx;
blockDlg[locBlockIdx] := true;
TDialogService.ShowMessage(AMessage,
procedure(const AResult: TModalResult)
begin
blockDlg[locBlockIdx] := false;
end);
while blockDlg[locBlockIdx] do begin
Sleep(40);
Application.ProcessMessages();
end;
end;
procedure NMessageDialogAsync(const AMessage: string; const ADialogType: TMsgDlgType;
const AButtons: TMsgDlgButtons; const ADefaultButton: TMsgDlgBtn;
const AHelpCtx: LongInt);
begin
TDialogService.MessageDialog(AMessage, ADialogType, AButtons, ADefaultButton,
AHelpCtx, procedure(const AResult: TModalResult) begin end);
end;
function NMessageDialogSync(const AMessage: string; const ADialogType: TMsgDlgType;
const AButtons: TMsgDlgButtons; const ADefaultButton: TMsgDlgBtn;
const AHelpCtx: LongInt): TModalResult;
var
locBlockIdx: Integer;
LModalResult: TModalResult;
begin
Result := -1;
if blockDlgIdx = Length(blockDlg)-1 then blockDlgIdx := 0 else Inc(blockDlgIdx);
locBlockIdx := blockDlgIdx;
blockDlg[locBlockIdx] := true;
TDialogService.MessageDialog(AMessage, ADialogType, AButtons, ADefaultButton, AHelpCtx,
procedure(const AResult: TModalResult)
begin
LModalResult := AResult;
blockDlg[locBlockIdx] := false;
end);
while blockDlg[locBlockIdx] do begin
Sleep(40);
Application.ProcessMessages();
end;
Result := LModalResult;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
mr: TModalResult;
begin
mr := NMessageDialogSync('1',
System.UITypes.TMsgDlgType.mtInformation,
[System.UITypes.TMsgDlgBtn.mbYes, System.UITypes.TMsgDlgBtn.mbNo, System.UITypes.TMsgDlgBtn.mbCancel],
System.UITypes.TMsgDlgBtn.mbYes,
0);
NShowMessageSync(IntToStr(mr));
mr := NMessageDialogSync('2',
System.UITypes.TMsgDlgType.mtWarning,
[System.UITypes.TMsgDlgBtn.mbYesToAll, System.UITypes.TMsgDlgBtn.mbAbort],
System.UITypes.TMsgDlgBtn.mbAbort,
0);
NShowMessageSync(IntToStr(mr));
mr := NMessageDialogSync('3',
System.UITypes.TMsgDlgType.mtInformation,
[System.UITypes.TMsgDlgBtn.mbIgnore, System.UITypes.TMsgDlgBtn.mbAll, System.UITypes.TMsgDlgBtn.mbHelp, System.UITypes.TMsgDlgBtn.mbClose],
System.UITypes.TMsgDlgBtn.mbClose,
0);
NShowMessageSync(IntToStr(mr));
Form1.Fill.Kind := TBrushKind.Solid;
if Form1.Fill.Color = TAlphaColors.Red then
Form1.Fill.Color := TAlphaColors.Blue
else
Form1.Fill.Color := TAlphaColors.Red;
end;
end.
Not very clean, but at least I can use this for a while.

Android push notification with actions/parameters

I just made an app with Delphi XE6 that receives push notifications with kinvey based on this example
When the application is running and I send a push the PushEvent handler receives it well, but when the application is closed and I press the notification it only opens my app.
Can I know which notification was pressed and get parameters from it?
Thanks in advance.
Edit:
I get a little bit closer, in my FormCreate ask for Extras:
procedure TForm1.FormCreate(Sender: TObject);
var
LIntent: JIntent;
LExtras: JBundle;
LExtrasArray: TJavaObjectArray<AndroidApi.JNI.JavaTypes.JObject>;
begin
LIntent := SharedActivity.getIntent;
try
if LIntent <> nil then
begin
LExtras := LIntent.getExtras;
if LExtras <> nil then
begin
//Now try to get the data
LExtrasArray := LExtras.KeySet.toArray;
for I := 0 to LExtrasArray.Length - 1 do
Memo1.Lines.Add(JStringToString(LExtrasArray.Items[I].toString));
end;
end;
finally
LIntent := nil;
end;
end;
With this code I get "gcm" in my memo.
So, when the notification fires my app I get this Extra available.
Now the problem is how I get info about that extra?
I tried LExtras.getString(StringToJString('message')) but this writes '' instead of the push message
Sarina DuPont answer me in her Blog
PushEvents component has a property StartupNotification for this purpose
procedure TMainForm.FormShow(Sender: TObject);
begin
if Assigned(PushEvents.StartupNotification) then
//Do something here!
//for example
//Memo.Text := PushEvents.StartupNotification.Message;
end;

Delphi XE5 Android Dev "unable to open database file"

I followed this tutorial step by step Mobile Tutorial: Using SQLite (iOS and Android) but when I deploy my application on my android device and attempt to add an entry, I get the following error "unable to open database file"
Here is a snippet of my code:
procedure TForm1.rappadAfterConnect(Sender: TObject);
begin
rappad.ExecuteDirect('CREATE TABLE IF NOT EXISTS notes(ID INTEGER PRIMARY KEY, title TEXT NOT NULL, content TEXT NOT NULL);');
end;
procedure TForm1.rappadBeforeDisconnect(Sender: TObject);
begin
{$IF DEFINED(iOS) or DEFINED(ANDROID)}
rappad.Params.Values['ColumnMetadataSupported'] := 'False';
rappad.Params.Values['Database'] :=
TPath.Combine(TPath.GetDocumentsPath, 'rappad.s3db');
{$ENDIF}
end;
Does anyone know why is this actually happening? Thanks!
The code you have in your rappadBeforeDisconnect needs to be in BeforeConnect instead. There's no point in telling the connection where the database is located before you disconnect.
procedure TForm1.rappadBeforeConnect(Sender: TObject);
begin
{$IF DEFINED(iOS) or DEFINED(ANDROID)}
rappad.Params.Values['ColumnMetadataSupported'] := 'False';
rappad.Params.Values['Database'] :=
TPath.Combine(TPath.GetDocumentsPath, 'rappad.s3db');
{$ENDIF}
end;

Delphi xe5 Android app freezes when accessing Clipboard

I am building an application for Android using Delphi XE5 that makes use of the Zxing barcode application and it uses the clipboard to retrieve the result. All of the code (Most of it anyway) is from a tutorial that I have found on the web. When I followed the tutorial, it worked to a charm but when applying the SAME code within an application that I was already working on - it did not work. Whenever accessing the clipboard ( in the 'OnTimer' event), the application always hangs and stops working. No error, nothing. App freezes and I have to close it via the phone's task manager.
The application fails right after the following line
Log.Add('AndroidClipboardScanner:1'); Log.SaveToFile(INIFileLog);
I have changed the coding around so that the app assumed the Clipboard service was available in the Ontimer event and it proceeded but it then failed after the following line:
Log.Add('AndroidClipboardScanner:4'); Log.SaveToFile(INIFileLog);
I am not sure where to begin debugging because the same code works in the other application that I created following the initial guide I found. I can also confirm that the ClipService is being assigned properly, otherwise the intent wouldn't even begin. Any help or guidance would be much appreciated ! Below is my code...
This Declared in the 'Private' variables section of the form:
ClipService: IFMXClipboardService;
This within the 'OnTimer' event for Timer1:
procedure TMain_Form.Timer1Timer(Sender: TObject);
var
barCode : String;
begin
timer1.Enabled := false;
Log.Add('AndroidClipboardScanner:0.1'); Log.SaveToFile(INIFileLog);
Try
if assigned(ClipService) then begin
Log.Add('AndroidClipboardScanner:1'); Log.SaveToFile(INIFileLog);
if (ClipService.GetClipboard.ToString <> 'nil') then
begin
Log.Add('AndroidClipboardScanner:2'); Log.SaveToFile(INIFileLog);
timer1.Enabled := false;
Log.Add('AndroidClipboardScanner:3'); Log.SaveToFile(INIFileLog);
Elapsed := 0;
Log.Add('AndroidClipboardScanner:4'); Log.SaveToFile(INIFileLog);
editHold.PasteFromClipboard;
//EditHold.Text := ClipService.GetClipboard.ToString;
Log.Add('AndroidClipboardScanner:5'); Log.SaveToFile(INIFileLog);
end else
begin
Log.Add('AndroidClipboardScanner:6'); Log.SaveToFile(INIFileLog);
Timer1.Enabled := False;
Log.Add('AndroidClipboardScanner:7'); Log.SaveToFile(INIFileLog);
end;
Log.Add('AndroidClipboardScanner:8'); Log.SaveToFile(INIFileLog);
end else begin
ShowMessage('Unexpected error has occured');
end;
Except
ShowMessage('Unexpected error has occured..');
End;
end;
Within the ONCreate procedure of the form:
if not TPlatformServices.Current.SupportsPlatformService(IFMXClipboardService,
IInterface(ClipService)) then begin
ShowMessage('Clipboard Failed:1');
ClipService := nil;
end;
Elapsed := 0;
This is for click event for the button that begins the intent:
procedure TMain_Form.Button_ShowScannerClick(Sender: TObject);
{$IFDEF ANDROID}
var
intent: JIntent; {$ENDIF}
begin
{$IFDEF ANDROID}
//ShowMessage('Scanner:1');
if assigned(ClipService) then begin
//ShowMessage('Scanner:2');
ClipService.SetClipboard('nil');
intent := tjintent.Create;
intent.setAction(stringtojstring('com.google.zxing.client.android.SCAN'));
intent.putExtra(tjintent.JavaClass.EXTRA_INTENT,
stringtojstring('"SCAN_MODE"'));
sharedactivity.startActivityForResult(intent,0);
Elapsed := 0;
timer1.Enabled := true;
//ShowMessage('Scanner:3');
end;
{$ENDIF}
You didn't set the SCAN_MODE parameters like:
intent.putExtra(tjintent.JavaClass.EXTRA_TEXT,
stringtojstring('"SCAN_MODE","ONE_D_MODE,QR_CODE_MODE,PRODUCT_MODE,DATA_MATRIX_MODE"'));
Also you can check timer interval parameter...
I tested the solution on few devices.
With low interval value I had black screen sometimes

Categories

Resources