Я прошел через множество ресурсов и, наконец, получил причину. Так или иначе, мое разрешение на манифест не получило разрешения на написание внешнего разрешения, как показано ниже.
blockquote><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Итак, что я сделал, я добавил разрешение времени выполнения для внешней записи, и оно работает нормально. я использую PermissionsAndroid из реактивный-родной .
коды ниже =>
try { const granted = await PermissionsAndroid.request( PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE, { title: "Cool Photo App Camera Permission", message: "Cool Photo App needs access to your camera " + "so you can take awesome pictures.", buttonNeutral: "Ask Me Later", buttonNegative: "Cancel", buttonPositive: "OK" } ); if (granted === PermissionsAndroid.RESULTS.GRANTED) { console.log("You can use the camera"); const data = await this.camera.takePictureAsync(); let saveResult = CameraRoll.saveToCameraRoll(data.uri); console.warn("takePicture ", saveResult); console.warn("picture url ", data.uri); } else { console.log("Camera permission denied"); } } catch (err) { console.warn(err); }
К сожалению, компилятор Delphi генерирует необходимый код для подсчета ссылок inc / dec только при использовании интерфейсов (в вашем случае пользовательский интерфейс IFileInfo). Более того, если интерфейсы приводятся к указателю (или TObject в этом отношении), опять же, подсчет ссылок невозможен. Например, предполагая, что список глобальных переменных: TList:
var ifi : IFileInfo;
begin
ifi := TFileInfo.Create;
list.Add(TFileInfo(ifi));
end;
после того, как метод возвращает список, [list.Count - 1] будет содержать висячий указатель.
Таким образом, интерфейсы нельзя использовать в хэш-карте, которая приводит их к указателям, реализация хэш-карты должен держать их как II-интерфейс.
Подсчет ссылок в Delphi работает, только если у вас есть ссылка на ваш экземпляр через интерфейс. Как только вы смешаете ссылки на интерфейсы и ссылки на классы, у вас возникнут проблемы.
По сути, вам нужен подсчет ссылок без необходимости создавать интерфейс со всеми методами и свойствами, определенными в нем. Есть три способа сделать это, и они примерно в том порядке, в котором я бы их порекомендовал.
Барри Келли написал пост о умных указателях . Он использует Generics в Delphi 2009, но я вполне уверен, что вы можете жестко закодировать его для конкретных версий типа, который вы используете, если вы еще не используете 2009 (это отличный выпуск BTW).
Другой способ, который работает с большим количеством версий Delphi и меньшей модификацией является оболочка типа значения от Janez Atmapuri Makovsek. Это пример, реализованный для TStringList, но вы можете адаптировать его для любого типа.
Третий способ - создать интерфейсный указатель (аналогично Smart Pointer Барри, но не такой умный). Я считаю, что в JCL есть такой, но я точно не помню деталей. По сути, это интерфейс, который принимает ссылку TObject при создании. Затем, когда счетчик ссылок достигает нуля, он вызывает free для объекта, который вы ему передали. Этот метод действительно работает только для кратковременных экземпляров, которые вы не передаете в качестве параметров, поскольку вы отделяете ссылку с подсчетом ссылок от фактически используемой ссылки. Вместо этого я бы порекомендовал один из двух других методов, но если вы предпочитаете этот метод и хотите больше информации, просто дайте мне знать.
В этом и заключается проблема Delphi, есть бесплатные способы выполнения задач. Вариант № 1, на мой взгляд, лучший - приобретите Delphi 2009 и используйте этот метод, если можете.
Удачи!
Не смешивайте ссылки на объекты и ссылки на интерфейсы.
var
Intf: IInterface;
Obj: TFileInfo;
begin
// Interface Reference
Intf := TFileInfo.Create; // Intf is freed by reference counting,
// because it's an interface reference
// Object Reference
Obj := TFileInfo.Create;
Obj.Free; // Free is necessary
// Dangerous: Mixing
Obj := TFileInfo.Create;
Intf := Obj; // Intf takes over ownership and destroys Obj when nil!
Intf := nil; // reference is destroyed here, and Obj now points to garbage
Obj.Free; // this will crash (AV) as Obj is not nil, but the underlying object
// is already destroyed
end;
Эта функциональность предоставляется для интерфейсов, но не для объектов.
Вы можете создать что-то подобное, но вам нужно переопределить некоторую структуру TObject:
TRefCountObject = class (TObject)
private
FRefCount : Integer;
public
constructor Create;
procedure Free; reintroduce;
function RefCountedCopy: TRefCountObject;
end;
constructor TRefCountObject.Create;
begin
inherited;
FRefCount := 1;
end;
procedure TRefCountObject.Free;
begin
if self=nil then Exit;
Dec(FRefCount);
if FRefCount<=0 then
Destroy;
end;
function TRefCountObject.RefCountedCopy: TRefCountObject;
begin
Inc(FRefCount);
Result := self;
end;
Вам нужен RefCountingCopy, чтобы назначить объект другой переменной. Но тогда у вас есть пересчитанный объект.
Как это использовать:
var1 := TRefCountObject.Create; // rc = 1
var2 := var1.RefCountedCopy; // rc = 2
var3 := var1.RefCountedCopy; // rc = 3
var2.Free; // rc = 2
var1.Free; // rc = 1
var4 := var3.RefCountedCopy; // rc = 2
var3.Free; // rc = 1
var4.Free; // rc = 0
Чтобы добавить к тому, что уже было сказано, если вы хотите хранить ссылки на интерфейсы, вместо использования TList используйте TInterfaceList . Счетчик ссылок будет работать последовательно.
Для этого есть длинное объяснение, но вкратце: наследования от TInterfacedObject (и не вызова Free самостоятельно) недостаточно, вам нужно использовать object-factory-dynamic для создания объектов для вас, и используйте интерфейсные указатели на объект повсюду, а не просто объект-ссылка-переменные. (Да, это означает, что вы не можете просто переключить «старый код», не просматривая его)
Если вы хотите исключить вызовы free в экземплярах TObject, то вам, возможно, стоит взглянуть на сборщик мусора для нативного Delphi. Я знаю о 2 разных сборщиках мусора и технике сбора мусора, каждый со своими плюсами и минусами.
Собственный сборщик мусора для точного отслеживания Хенрика Хеллстрема
API для DLL-сборщика мусора Boehm Барри Келли
Сборщик мусора для объектов и компонентов Delphi Росена Асенова (не настоящий мусор) коллекционер, скорее мешок памяти.)
Один из них, вероятно, подойдет вам.