Search the Community
Showing results for tags 'camera'.
Found 5 results
-
TakePhotoAction crashes android app and starts again on xiaomi Android 12
fisipjm posted a topic in FMX
Crosspost Stackoverflow Environment: Delphi 12.2 (latest SP) APP for Android and iOS Hardware Pixel 7a (Android 15) / Xiaomi Redmi (Android 12 SP1) Problem: The issue only happens on the Xiaomi device (or possibly other brands I haven’t tested). It works fine on the Pixel. In my project, I load data from an API endpoint into a local SQLite database. Then, I take photos and save them alongside the downloaded data. Here is the problematic code: procedure TPhotoForm.TakePicture(Sender: TObject); begin if TOSVersion.Check(11) then ActionTakePhotoFromCamera.Execute; end; I’m using the exact same code from the Embarcadero example: https://docwiki.embarcadero.com/CodeExamples/Athens/en/FMX.PhotoEditorDemo_Sample The issue happens after calling the procedure. The system camera opens, and I can take a picture. However, when I select the picture (to trigger the OnFinishTakingPicture event), the app crashes. There’s no error message—the app just restarts like I launched it again. Here’s the twist: this doesn’t happen every time. After a few retries (3–4 attempts), or if I restart the app, the photo-taking process works fine. Once it works, it will keep working—unless I restart the app. To reproduce the issue consistently: Uninstall the app Reinstall it Take a photo on the first run. The crash happens every time in this scenario. Investigations so far: What works The sample app from Embarcadero works perfectly on the Xiaomi device. After realizing this, I tested a few things: Access rights At first, I thought it was an issue with access rights or the Android manifest. I updated everything to match the demo project. I also discovered that you don’t actually need camera permissions when using the system camera dialog. Interesting, but it didn’t help—the issue still occurs. Bug in FMX.MediaLibrary.Android Next, I looked deeper into the code for `TAction.TakePhoto`. I traced it to `FMX.MediaLibrary.Android`. There are two key methods I investigated: - `TImageManagerAndroid.TakePhoto` - `TImageManagerAndroid.TPhotoActivityResponseListener.onResponse` `TakePhoto` passes the required data to `FActivityClient.TakePhoto(LRequestParams);`, which is implemented in a JAR file. This always works as expected—it launches the system camera dialog. The `onResponse` method is called every time the camera dialog closes, even when the app crashes. If the app crashes, first, `Application.Run` is triggered, then `TPhotoActivityResponseListener.onResponse`. But when the app crashes, `LParams.OnDidFinishTaking` is invalid because the app restarts. So everything looks fine here—no obvious issues. Energy management It feels like some kind of battery-saving issue. Maybe Android is trying to free up resources and closes my app while the camera is open. To test this, I manually installed the APK and disabled all battery optimizations for my app. The crash still happened. Log Files I also checked the ADB logs. There’s a specific message logged every time the crash occurs, but I couldn’t find any information about it online neither do I know if this is a Problem or not. Here’s a snippet from the logs: 2025.01.23 09:48:27.293 W 5929 System.err org.json.JSONException: No value for cannong 2025.01.23 09:48:27.298 W 5929 System.err at org.json.JSONObject.get(JSONObject.java:398) 2025.01.23 09:48:27.298 W 5929 System.err at org.json.JSONObject.getJSONObject(JSONObject.java:618) 2025.01.23 09:48:27.298 W 5929 System.err at android.util.MiuiMultiWindowUtils.initFreeFormResolutionArgsOfDevice(MiuiMultiWindowUtils.java:1436) 2025.01.23 09:48:27.298 W 5929 System.err at android.util.MiuiMultiWindowUtils.initFreeFormResolutionArgs(MiuiMultiWindowUtils.java:1430) 2025.01.23 09:48:27.298 W 5929 System.err at android.util.MiuiMultiWindowUtils.<clinit>(MiuiMultiWindowUtils.java:212) 2025.01.23 09:48:27.298 W 5929 System.err at com.android.internal.policy.DecorViewMultiWinStubImpl.<init>(DecorViewMultiWinStubImpl.java:19) 2025.01.23 09:48:27.298 W 5929 System.err at com.android.internal.policy.DecorViewMultiWinStubImpl$Provider.provideNewInstance(DecorViewMultiWinStubImpl$Provider.java:14) 2025.01.23 09:48:27.298 W 5929 System.err at com.android.internal.policy.DecorViewMultiWinStubImpl$Provider.provideNewInstance(DecorViewMultiWinStubImpl$Provider.java:8) 2025.01.23 09:48:27.298 W 5929 System.err at com.miui.base.MiuiStubRegistry.get(MiuiStubRegistry.java:129) 2025.01.23 09:48:27.298 W 5929 System.err at com.miui.base.MiuiStubUtil.newInstance(MiuiStubUtil.java:77) 2025.01.23 09:48:27.298 W 5929 System.err at com.android.internal.policy.DecorViewMultiWinStub.newInstance(DecorViewMultiWinStub.java:11) 2025.01.23 09:48:27.298 W 5929 System.err at com.android.internal.policy.DecorView.<init>(DecorView.java:335) 2025.01.23 09:48:27.298 W 5929 System.err at com.android.internal.policy.PhoneWindow.generateDecor(PhoneWindow.java:2380) 2025.01.23 09:48:27.298 W 5929 System.err at com.android.internal.policy.PhoneWindow.installDecor(PhoneWindow.java:2760) 2025.01.23 09:48:27.299 W 5929 System.err at com.android.internal.policy.PhoneWindow.getDecorView(PhoneWindow.java:2140) 2025.01.23 09:48:27.299 W 5929 System.err at android.view.Window.findViewById(Window.java:1516) 2025.01.23 09:48:27.299 W 5929 System.err at android.app.Activity.findViewById(Activity.java:3492) 2025.01.23 09:48:27.299 W 5929 System.err at com.embarcadero.firemonkey.keyboard.VirtualKeyboardFrameObserver.<init>(VirtualKeyboardFrameObserver.java:56) 2025.01.23 09:48:27.299 W 5929 System.err at com.embarcadero.firemonkey.keyboard.VirtualKeyboard.<init>(VirtualKeyboard.java:41) 2025.01.23 09:48:27.299 W 5929 System.err at com.embarcadero.firemonkey.FMXNativeActivity.onCreate(FMXNativeActivity.java:125) 2025.01.23 09:48:27.299 W 5929 System.err at android.app.Activity.performCreate(Activity.java:8176) 2025.01.23 09:48:27.299 W 5929 System.err at android.app.Activity.performCreate(Activity.java:8143) 2025.01.23 09:48:27.299 W 5929 System.err at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1329) 2025.01.23 09:48:27.299 W 5929 System.err at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3752) 2025.01.23 09:48:27.299 W 5929 System.err at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3946) 2025.01.23 09:48:27.299 W 5929 System.err at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:106) 2025.01.23 09:48:27.299 W 5929 System.err at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135) 2025.01.23 09:48:27.299 W 5929 System.err at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95) 2025.01.23 09:48:27.299 W 5929 System.err at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2324) 2025.01.23 09:48:27.299 W 5929 System.err at android.os.Handler.dispatchMessage(Handler.java:106) 2025.01.23 09:48:27.300 W 5929 System.err at android.os.Looper.loopOnce(Looper.java:210) 2025.01.23 09:48:27.300 W 5929 System.err at android.os.Looper.loop(Looper.java:299) 2025.01.23 09:48:27.300 W 5929 System.err at android.app.ActivityThread.main(ActivityThread.java:8273) 2025.01.23 09:48:27.300 W 5929 System.err at java.lang.reflect.Method.invoke(Native Method) 2025.01.23 09:48:27.300 W 5929 System.err at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:576) 2025.01.23 09:48:27.300 W 5929 System.err at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1073) So, after all this, I’m running out of ideas on how to solve this problem. At this point, it feels like Android is terminating some background processes, which causes my app to crash. This might be happening because my app uses more RAM compared to a simple demo application like the one provided by Emba. Does anyone else have experience with this issue or any suggestions on how to move forward? Any help would be greatly appreciated. Best Regards PJM -
Hello, I'm evaluating latest version of Delphi RAD for possible iOS/android phone application. I'd like to be able to use a phone camera (iOS and Android) to take photos (maybe 1 per second) and upload to my server. So.. 1). I found sample project "accessCameraApp" - my first question is.. would this be the component to use for my photo capture? - or should I be using something different? 2) I found internet references to indy components (I have used this in the past), but they are not installed on my component palette (no problem though I guess I can install later), but I did find TNetHTTPClient and TNetHTTPRequest, I was wondering which I should use (indy/TNetHTTPClient or maybe synapse if it is available?) for posting photo frames to my server? (i.e. a php page that saves photo(s) in database BLOB field). Any help to point me in the right direction would be great, it's more about the selection of components that I would need, I have plenty of Object Pascal experience, and I do a lot of camera work using javascript. It's just that the latest set of Delphi tools are new to me. Thanks in advance, Mike
-
my sample based on tip by Fernando Rizzato (MVP Embarcadero lead South America) unit uFormMain; interface uses System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants, System.Permissions, FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.Layouts, FMX.Controls.Presentation, FMX.StdCtrls, FMX.ListBox, FMX.Objects, FMX.ScrollBox, FMX.Memo, FMX.Media; type TfrmFormMain = class(TForm) lytFormMain: TLayout; lytFormMainToolBar: TLayout; lytFormMainClientArea: TLayout; tbarFormMainMenu: TToolBar; sbtnCAMStartCamera: TSpeedButton; cmbboxCAMDevices: TComboBox; imgVideoCapture: TImage; mmMyLog: TMemo; sbtnCAMStopCamera: TSpeedButton; procedure FormCreate(Sender: TObject); procedure sbtnCAMStartCameraClick(Sender: TObject); procedure FormClose(Sender: TObject; var Action: TCloseAction); procedure imgVideoCaptureTap(Sender: TObject; const Point: TPointF); procedure sbtnCAMStopCameraClick(Sender: TObject); procedure cmbboxCAMDevicesChange(Sender: TObject); procedure FormResize(Sender: TObject); procedure FormActivate(Sender: TObject); private procedure prcMyLog(lText: string); // procedure prcCAMDevicesSetting; procedure prcCAMStartCapture; // {$IF DEFINED(ANDROID)} procedure prcPermissionsResulted(Sender: TObject; const APermissions: TArray<string>; const AGrantResults: TArray<TPermissionStatus>); procedure prcDisplayRationale(Sender: TObject; const APermissions: TArray<string>; const APostRationaleProc: TProc); {$ENDIF} // procedure prcCAMSampleBufferReady(Sender: TObject; const ATime: TMediaTime); procedure prcCAMSampleBufferSync; public end; var frmFormMain : TfrmFormMain; FFormTopPositionBeforeResize: integer = 0; implementation {$R *.fmx} { This sample, will use the "TVideoCaptureDevice" (class base to "TCameraComponent") directly!!! This class is defined in "FMX.Media.pas" // TDialogService.ShowMessage() used for dont block main-thread! } // uses FMX.DialogService {$IF DEFINED(ANDROID)} , FMX.Helpers.Android, Androidapi.JNI.JavaTypes, Androidapi.Helpers, Androidapi.JNI.OS {$ENDIF} ; // var lMyCAMDevice : TVideoCaptureDevice; lMyCAMPermission: string; function fncMyIIF(lBooleanExpr: boolean; lTextTrue, lTextFalse: string): string; begin result := lTextFalse; // if lBooleanExpr then result := lTextTrue; end; procedure TfrmFormMain.prcMyLog(lText: string); begin mmMyLog.Lines.Add(lText); end; procedure TfrmFormMain.cmbboxCAMDevicesChange(Sender: TObject); begin {$IF NOT DEFINED(ANDROID)} try lMyCAMDevice := nil; // lMyCAMDevice := TVideoCaptureDevice(TCaptureDeviceManager.Current.GetDevicesByName(cmbboxCAMDevices.Selected.Text)); // sbtnCAMStartCamera.Enabled := not(lMyCAMDevice = nil); // except on E: Exception do prcMyLog('Error Start CAM' + #13#10 + E.Message); end; {$ENDIF} end; procedure TfrmFormMain.FormActivate(Sender: TObject); begin {$IF NOT DEFINED(ANDROID)} FFormTopPositionBeforeResize := Self.Top; { when the user move the forms, needs change it too! } {$ENDIF} end; procedure TfrmFormMain.FormClose(Sender: TObject; var Action: TCloseAction); begin if not(lMyCAMDevice = nil) then begin {$IF DEFINED(ANDROID)} // if PermissionsService.IsEveryPermissionGranted([lMyCAMPermission]) then; if PermissionsService.IsPermissionGranted(lMyCAMPermission) then {$ENDIF} begin if (lMyCAMDevice.State = TCaptureDeviceState.Capturing) then lMyCAMDevice.StopCapture; end; // // lMyCAMDevice.Free; // if necessary!!! end; end; procedure TfrmFormMain.FormCreate(Sender: TObject); begin {$IF NOT DEFINED(ANDROID)} FFormTopPositionBeforeResize := Self.Top; {$ENDIF} // // // Form.OnCreate is not better place to "critial" procedure! // Here, only basic procedures! // Self.Position := TFormPosition.ScreenCenter; sbtnCAMStopCamera.Text := 'Stop Cam'; // prcCAMDevicesSetting; // if necessary, move it for another place! // if not(lMyCAMDevice = nil) then begin prcMyLog(lMyCAMDevice.ToString); // unfortunatelly, dont have Name or Description on Mobile Android // sbtnCAMStartCamera.Enabled := True; end else prcMyLog('MyCAMDevice = nil'); end; procedure TfrmFormMain.FormResize(Sender: TObject); begin {$IF NOT DEFINED(ANDROID)} if (Self.Height <= 480) then begin Self.Top := FFormTopPositionBeforeResize; Self.Height := 480; end; // if (Self.Width <= 640) then Self.Width := 640; // to avoid that ComboBox is gone...! {$ENDIF} end; procedure TfrmFormMain.imgVideoCaptureTap(Sender: TObject; const Point: TPointF); {$IF DEFINED(ANDROID)} var lObject: string; {$ENDIF} begin {$IF DEFINED(ANDROID)} // for "TAPing" tests! // lObject := ''; // if not(Sender = nil) then lObject := Sender.ClassName; // TDialogService.ShowMessage( { } Format('Object=%s, Point X=%f, Y=%f, V[0]=%f, V[1]=%f, IsZero=%s', [ { } lObject, Point.X, Point.Y, Point.V[0], Point.V[1], { } fncMyIIF(Point.IsZero, 'is zero', 'is not zero') { } ])); {$ENDIF} end; procedure TfrmFormMain.prcCAMDevicesSetting; {$IF NOT DEFINED(ANDROID)} var DeviceList: TCaptureDeviceList; i : integer; {$ENDIF} begin {$IF DEFINED(ANDROID)} cmbboxCAMDevices.Visible := False; try // Normally, there is only 1 cam in Mobile! // // NOTE: any try to read or change any property from CAM, NEEDS "permissions"!!! lMyCAMDevice := TCaptureDeviceManager.Current.DefaultVideoCaptureDevice; // lMyCAMDevice.OnSampleBufferReady := prcCAMSampleBufferReady; // showing our video on TImage // // DONT TRY READ or CHANGE any property from CAMDevice here!!! // Like: Start or Stop, Quality, IsDefault, etc... // Only later your "permissions" to be given by user!!! except on E: Exception do prcMyLog('Error CAM definition' + #13#10 + E.Message); end; {$ELSE} DeviceList := TCaptureDeviceManager.Current.GetDevicesByMediaType(TMediaType.Video); // for i := 0 to (DeviceList.Count - 1) do cmbboxCAMDevices.Items.Add(DeviceList[i].Name); {$ENDIF} end; {$IF DEFINED(ANDROID)} // DisplayRationale and PermissionsResulted is used only mobile! procedure TfrmFormMain.prcDisplayRationale(Sender: TObject; const APermissions: TArray<string>; const APostRationaleProc: TProc); var lRationaleMsg: string; i : integer; begin for i := 0 to high(APermissions) do begin if APermissions[i] = lMyCAMPermission then lRationaleMsg := lRationaleMsg + 'This app needs access your CAM to works' + SLineBreak + SLineBreak; end; // // Show an explanation to the user *asynchronously* - don't block this thread waiting for the user's response! // After the user sees the explanation, invoke the post-rationale routine to request the permissions // TDialogService.ShowMessage(lRationaleMsg, procedure(const AResult: TModalResult) begin // TProc is defined in System.SysUtils // APostRationaleProc; // used by System to go-back in before function... end) end; procedure TfrmFormMain.prcPermissionsResulted(Sender: TObject; const APermissions: TArray<string>; const AGrantResults: TArray<TPermissionStatus>); begin // verifying if the permissions was granted! - Here, testing only 1 permission = CAM if (Length(AGrantResults) = 1) and (AGrantResults[0] = TPermissionStatus.Granted) then prcCAMStartCapture { execute your procedure here if all it's ok } else TDialogService.ShowMessage('The permission <<CAMERA access>> not allowed by user'); end; {$ENDIF} procedure TfrmFormMain.prcCAMSampleBufferReady(Sender: TObject; const ATime: TMediaTime); begin // ****** // DONT USE "main thread" to process something "critial" like: process images by Cam // or anyother that can "crash" your UI (user interface) or app!!! // *************************************************************** // If exist images to process, then, put it on a "queue" to execute it! // Here, "prcSampleBufferSync" will be called always in a queue from main thread (your app) // to "dont paralize it" while the images it's processed!!! // // .............."main thread".........."method called" // TThread.Queue(TThread.CurrentThread, prcCAMSampleBufferSync); // end; procedure TfrmFormMain.prcCAMSampleBufferSync; begin // // use your imagination, to redirect this buffer !!! :) // // in the meantime ... let's write the pictures coming from the camera in the TImage lMyCAMDevice.SampleBufferToBitmap(imgVideoCapture.Bitmap, True); // end; procedure TfrmFormMain.prcCAMStartCapture; begin if not(lMyCAMDevice = nil) then begin // to Mobile (Android), change properties from CAMERA, needs permission! {$IF DEFINED(ANDROID)} if PermissionsService.IsPermissionGranted(lMyCAMPermission) then {$ENDIF} begin try lMyCAMDevice.StopCapture; // to avoid any error below // lMyCAMDevice.Quality := TVideoCaptureQuality.PhotoQuality; // lMyCAMDevice.StartCapture; // starting video capture! // prcMyLog('CAM device = Capture stated!'); prcMyLog('CAM ' + fncMyIIF(lMyCAMDevice.IsDefault, 'is', 'is not') + ' Default'); prcMyLog('CAM ' + fncMyIIF(lMyCAMDevice.HasFlash, 'has', 'has not') + ' Flash'); except on E: Exception do prcMyLog('Error Start CAM' + #13#10 + E.Message); end; end {$IF DEFINED(ANDROID)} else TDialogService.ShowMessage('Then CAM device needs your permission to access it!'); {$ENDIF} end else TDialogService.ShowMessage('None CAM device defined!'); end; procedure TfrmFormMain.sbtnCAMStopCameraClick(Sender: TObject); begin if not(lMyCAMDevice = nil) then begin // Needs "permissions" to read or change CAM properties! // {$IF DEFINED(ANDROID)} if PermissionsService.IsPermissionGranted(lMyCAMPermission) then {$ENDIF} begin if (lMyCAMDevice.State = TCaptureDeviceState.Capturing) then lMyCAMDevice.StopCapture else lMyCAMDevice.StartCapture; end {$IF DEFINED(ANDROID)} else TDialogService.ShowMessage('The <<CAMERA access>> permission is necessary'); {$ENDIF} end; end; procedure TfrmFormMain.sbtnCAMStartCameraClick(Sender: TObject); begin {$IF DEFINED(ANDROID)} PermissionsService.RequestPermissions( { } [lMyCAMPermission], { } prcPermissionsResulted, { } prcDisplayRationale { = nil, if you DONT WANT show any message! } ); {$ELSE} prcCAMStartCapture; // MSWindows or macOS {$ENDIF} end; initialization lMyCAMDevice := nil; {$IF DEFINED(ANDROID)} lMyCAMPermission := JStringToString(TJManifest_permission.JavaClass.CAMERA); {$ENDIF} finalization end. hug
-
gallery Android 10 delphi 10.4 camera and gallery doesn't work
Massimiliano S posted a topic in Cross-platform
Hi, After updating to delphi 10.4 and SDK 29 the camera and gallery do not work on Android 10 Also delphi examples don't work. After taking a photo from the camera the app doesn't return anything while the gallery, after choosing the photo, raises this execption First chance exception at $ 00000074D87D473C. Exception class EBitmapLoadingFailed with message 'Loading bitmap failed (/data/user/0/com.embarcadero.CameraRoll/cache/IMG_20200911_1728082355078942815963051.jpg).'. Process CameraRoll.apk (11714) any ideas? -
I use Tcameracomponent in delphi to take a picture, when I take a picture use back camera is ok, but when I use front camera the result is flipped. how to take picture from front camera like back camera?
- 2 replies
-
- camera
- tcameracomponent
-
(and 1 more)
Tagged with: