如何在DelphiAndroid应用中调用原生相机?
How to invoke native camera in Delphi Android application?
我正在使用 Delphi 10.3 Community Edition 编写一个简单的 Android 应用程序并尝试调用本机设备相机,但出现错误。
我在关注官方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.
我已验证项目 |选项 |使用权限 - 相机设置设为 true
。我也在请求启动应用程序所需的权限。 Debug 或 Release 中 运行 没有区别。
但是有一个问题。单击按钮时出现以下错误消息:
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.
这是我为最简单的测试应用编写的代码:
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.
如何让原生相机TTakePhotoFromCameraAction生效?
检查项目选项 > 权利列表 > 安全文件共享选项是否设置为 true
。
对于将项目从旧版本移植到 10.3 的任何人,请确保您的 AndroidManifest.xml 在 <%application-meta-data%> 标记正上方包含 <%provider%> 标记。
我在其他方面和这里发现的很多评论都建议可以在此处找到此文件:
C:\Users\(yourusername)\AppData\Roaming\Embarcadero\BDS.0\AndroidManifest.xml
但如果这不起作用,那么您的 源目录 中可能已经有一个 AndroidManifest.template.xml
文件。如果是这样,那么编译器将使用此模板文件并忽略 AppData 文件夹中的文件!
我遇到了 Android 9 可以工作但某些设备 运行 Android 10 不能工作的问题。我需要执行上面列出的答案中的步骤,但我的仍然无法正常工作,直到我添加:
android:requestLegacyExternalStorage="true"
到我的AndroidManifest.template.xml
的申请部分
我正在使用 Delphi 10.3 Community Edition 编写一个简单的 Android 应用程序并尝试调用本机设备相机,但出现错误。
我在关注官方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.
我已验证项目 |选项 |使用权限 - 相机设置设为 true
。我也在请求启动应用程序所需的权限。 Debug 或 Release 中 运行 没有区别。
但是有一个问题。单击按钮时出现以下错误消息:
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.
这是我为最简单的测试应用编写的代码:
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.
如何让原生相机TTakePhotoFromCameraAction生效?
检查项目选项 > 权利列表 > 安全文件共享选项是否设置为 true
。
对于将项目从旧版本移植到 10.3 的任何人,请确保您的 AndroidManifest.xml 在 <%application-meta-data%> 标记正上方包含 <%provider%> 标记。
我在其他方面和这里发现的很多评论都建议可以在此处找到此文件:
C:\Users\(yourusername)\AppData\Roaming\Embarcadero\BDS.0\AndroidManifest.xml
但如果这不起作用,那么您的 源目录 中可能已经有一个 AndroidManifest.template.xml
文件。如果是这样,那么编译器将使用此模板文件并忽略 AppData 文件夹中的文件!
我遇到了 Android 9 可以工作但某些设备 运行 Android 10 不能工作的问题。我需要执行上面列出的答案中的步骤,但我的仍然无法正常工作,直到我添加:
android:requestLegacyExternalStorage="true"
到我的AndroidManifest.template.xml
的申请部分