代码之家  ›  专栏  ›  技术社区  ›  Kromster Satyajit

如何在Delphi Android应用程序中调用本机摄像头?

  •  3
  • Kromster Satyajit  · 技术社区  · 6 年前

    我正在使用Delphi10.3社区版来编写一个简单的Android应用程序,并试图调用本机设备摄像头,但却出现了一个错误。

    我在跟踪官方的德尔菲 guide :

    在表单设计器上,选择按钮(用于拍照)。 在“对象检查器”中,选择“操作”属性的下拉列表。 从CameraAction中选择新建标准动作|媒体库| TTakPhoto:

    在“事件”选项卡上,展开“操作”节点,然后双击OnDidFinishTaking事件。

    将以下代码添加到OnDidFinishTaking事件处理程序:

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

    此代码将从移动设备照相机拍摄的照片分配给TImage组件的位图属性。

    我已验证项目|选项|使用权限-相机设置设置为 true

    然而,有一个问题。单击按钮时,我收到以下错误消息:

    java.lang.NullPointerException:尝试在空对象引用上调用虚拟方法“android.content.res.XmlResourceParser android.content.pm.PackageItemInfo.loadXmlMetaData(android.content.pm.PackageManager,java.lang.String)”。

    以下是我为最简单的测试应用程序编写的代码:

    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.
    

    1 回复  |  直到 6 年前
        1
  •  12
  •   Kromster Satyajit    6 年前

    检查项目选项是否>权利清单>安全文件共享选项设置为 true .

        2
  •  2
  •   user3437976    5 年前

    对于任何将项目从旧版本移植到10.3的人,请确保您的AndroidManifest.xml包含<%提供商%>标签位于<%的正上方应用程序元数据%>标签

    我在其他方面找到了很多评论,这里建议可以在这里找到此文件:

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

    AndroidManifest.template.xml 源目录 . 如果是这种情况,那么编译器将使用此模板文件并忽略AppData文件夹中的文件!

        3
  •  1
  •   chemish    4 年前

    我遇到了安卓9可以工作的问题,但一些运行安卓10的设备却不能。我需要执行上面列出的答案中的步骤,但我的步骤仍然不起作用,直到我添加:

    android:requestLegacyExternalStorage=“true”

    到我的AndroidManifest.template.xml的应用程序部分