Как вызвать родную камеру в приложении Delphi для Android?
Я использую Delphi 10.3 Community Edition для написания простого приложения для Android и пытаюсь вызвать собственную камеру устройства, но вместо этого получаю сообщение об ошибке.
Я следую официальному руководству Delphi:
В конструкторе форм выберите кнопку (для фотографирования). В Инспекторе объектов выберите раскрывающийся список для свойства "Действие". Выберите новое стандартное действие | Медиатека | TTakePhotoFromCameraAction:
На вкладке "События" разверните узел "Действие", а затем дважды щелкните событие OnDidFinishTaking.
Добавьте следующий код в обработчик события OnDidFinishTaking:
procedure TForm1.TakePhotoFromCameraAction1DidFinishTaking(Image: TBitmap); begin Image1.Bitmap.Assign(Image); end;
Этот код назначает снимок, сделанный камерой мобильного устройства, свойству Bitmap компонента TImage.
Я подтвердил, что проект | Варианты | Использует разрешения - настройка камеры установлена на true
, Я также запрашиваю разрешение на запуск приложения. Нет разницы между выполнением в Debug или Release.
Однако есть проблема. При нажатии на кнопку я получаю следующее сообщение об ошибке:
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.
Как заставить работать штатную камеру TTakePhotoFromCameraAction?
3 ответа
Убедитесь, что для параметров проекта> Список прав> Параметр безопасного доступа к файлам установлено значение true
,
Для тех, кто переносит проект со старой версии на 10.3, убедитесь, что ваш AndroidManifest.xml включает тег <% provider%> прямо над тегом <% application-meta-data%>.
Я нашел много комментариев с других сторон, и здесь предполагается, что этот файл можно найти здесь:
C:\Users\(yourusername)\AppData\Roaming\Embarcadero\BDS\20.0\AndroidManifest.xml
Но если это не сработает, вероятно, у вас уже есть AndroidManifest.template.xml
файл в исходном каталоге. Если это так, то компилятор будет использовать этот файл шаблона и игнорировать файл в папке AppData!
У меня были проблемы, когда Android 9 работал, а некоторые устройства под управлением Android 10 — нет. Мне нужно было выполнить шаги в ответах, перечисленных выше, но мой все еще не работал, пока я не добавил:
Android: requestLegacyExternalStorage = "истина"
в раздел приложения моего AndroidManifest.template.xml