4

I'm using Delphi 10.3 Community Edition to write a simple Android app and trying to invoke native device camera, but getting an error instead.

I'm following the official Delphi guide:

On the Form Designer, select the button (for taking a photo). In the Object Inspector, select the drop-down list for the Action property. Select New Standard Action | Media Library | TTakePhotoFromCameraAction:

On the Events tab, expand the Action node, and then double-click the OnDidFinishTaking event.

Add the following code to the OnDidFinishTaking event handler:

procedure TForm1.TakePhotoFromCameraAction1DidFinishTaking(Image: TBitmap);
begin
  Image1.Bitmap.Assign(Image);
end;

This code assigns a picture taken from the mobile device camera to the Bitmap property of the TImage component.

I have verified that Project | Options | Uses Permissions - Camera setting is set to true. I'm requesting required permission on the app start as well. There's no difference between running in Debug or Release.

However there is a problem. When clicking the button I get the following error message:

java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.res.XmlResourceParser android.content.pm.PackageItemInfo.loadXmlMetaData(android.content.pm.PackageManager, java.lang.String)' on a null object reference.

Here's the code I've written for the simplest test app:

unit Unit1;
interface
uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, System.Permissions,
  FMX.StdCtrls, FMX.MediaLibrary, FMX.Platform, System.Messaging, FMX.Objects,
  System.Actions, FMX.ActnList, FMX.StdActns, FMX.MediaLibrary.Actions,
  FMX.Controls.Presentation;

type
  TForm1 = class(TForm)
    Button1: TButton;
    ActionList1: TActionList;
    TakePhotoFromCameraAction1: TTakePhotoFromCameraAction;
    procedure FormCreate(Sender: TObject);
  private
    procedure PermissionRequestResult(Sender: TObject; const APermissions: TArray<string>; const AGrantResults: TArray<TPermissionStatus>);
    procedure DisplayRationale(Sender: TObject; const APermissions: TArray<string>; const APostRationaleProc: TProc);
  end;

var
  Form1: TForm1;

implementation
uses
{$IFDEF ANDROID}
  Androidapi.Helpers,
  Androidapi.JNI.JavaTypes,
  Androidapi.JNI.Os,
{$ENDIF}
  FMX.DialogService;

{$R *.fmx}

procedure TForm1.PermissionRequestResult(Sender: TObject; const APermissions: TArray<string>; const AGrantResults: TArray<TPermissionStatus>);
begin
  // 3 permission involved
  if (Length(AGrantResults) = 3)
  and (AGrantResults[0] = TPermissionStatus.Granted)
  and (AGrantResults[1] = TPermissionStatus.Granted)
  and (AGrantResults[2] = TPermissionStatus.Granted) then
  else
    ShowMessage('Required permission has not been granted') ;
end;

procedure TForm1.DisplayRationale(Sender: TObject; const APermissions: TArray<string>; const APostRationaleProc: TProc);
begin
  TDialogService.ShowMessage('Need to access the camera',
    procedure(const AResult: TModalResult)
    begin
      APostRationaleProc;
    end);
end;

procedure TForm1.FormCreate(Sender: TObject);
var
  permCam, permRead, permWrite: string;
begin
  // Request permissions
  permCam := JStringToString(TJManifest_permission.JavaClass.CAMERA);
  permRead := JStringToString(TJManifest_permission.JavaClass.READ_EXTERNAL_STORAGE);
  permWrite := JStringToString(TJManifest_permission.JavaClass.WRITE_EXTERNAL_STORAGE);
  PermissionsService.RequestPermissions([permCam, permRead, permWrite], PermissionRequestResult, DisplayRationale);
end;

end.

How to make the native camera TTakePhotoFromCameraAction to work?

Kromster
  • 6,665
  • 7
  • 55
  • 98

3 Answers3

12

Check that the Project Options > Entitlements List > Secure File Sharing option is set to true.

Kromster
  • 6,665
  • 7
  • 55
  • 98
Dave Nottage
  • 2,729
  • 1
  • 16
  • 38
  • I have the same problem. I have checked the secure file sharing option but i receive the error message mentioned by Kromster. I suppose something else needed. – JimPapas Feb 25 '19 at 23:41
  • 2
    More than likely you have an AndroidManifest.template.xml that does not have a tag because your app was created using an earlier version of Delphi. You can add it manually, just above the tag – Dave Nottage Feb 25 '19 at 23:48
  • Indeed there isn't tag but i wrote the app today with Delphi 10.3 CE. What should be the contents of this tag, please ? – JimPapas Feb 26 '19 at 00:12
  • 1
    There are no contents - the IDE will populate it into the AndroidManifest.xml when you deploy the app. If the tag was not there when you created the app, check if it exists in the file C:\Users\(yourusername)\AppData\Roaming\Embarcadero\BDS\20.0\AndroidManifest.xml, which is what Delphi uses to create AndroidManifest.template.xml. If the tag is not there, it likely means you had a beta version on the machine beforehand – Dave Nottage Feb 26 '19 at 00:18
  • 1
    I don't know why but with the new compilation the tag was there and the app worked fine (it can take pictures without problem). Thank you very much – JimPapas Feb 26 '19 at 00:34
  • One more question if you please. Why takes two photos (one about 300KB and one about 7 MB) each time i click the button ? – JimPapas Feb 26 '19 at 00:42
  • You might want to ask that as a separate question, showing the code that you're using. – Dave Nottage Feb 26 '19 at 00:43
  • 1
    Thanks it worked! It was the missing tag. I previously built in 10.2. After I upgraded to 10.3 looks like it was missing from the manifest file. Inside the project directory there is also a manifest file, so I recommend edit that one too. – Nico Dreyer May 08 '19 at 16:28
2

For anyone porting a project from an older version to 10.3, make sure that your AndroidManifest.xml includes the <%provider%> tag right above the <%application-meta-data%> tag.

A lot of comments I've found on other sides and here are suggesting that this file can be found here:

C:\Users\(yourusername)\AppData\Roaming\Embarcadero\BDS\20.0\AndroidManifest.xml

But if that doesn't work then you likely already have an AndroidManifest.template.xml file in your source directory. If that is the case then the compiler will use this template file and ignore the file in the AppData folder!

user3437976
  • 61
  • 1
  • 5
1

I was having issues where Android 9 would work but some devices running Android 10 wouldn't. I needed to do the steps in the answers listed above but mine was still not working until I added:

android:requestLegacyExternalStorage="true"

to the application section of my AndroidManifest.template.xml

chemish
  • 11
  • 1