Перейти к содержанию
Fire Monkey от А до Я
  • 0

TakePhotoFromCameraAction


Edward Tarasov

Вопрос

Всем дорого времени суток. столкнулся с такой проблемой. приложение под андройд вылетает и само перезапускается!! при использовании TakePhotoFromCameraAction в момент нажатия кнопки фото. т.е. при отладке видно что оно вылетело - причем без ошибок. а когда пытаешься вернутся на форму с которой ушел в TakePhotoFromCameraAction, появляется splashscreen и приложение загружается снова. что это?))!??? я в шоке)! может кто сталкивался? 

Пробовал менять Maxwith и MaxHeigth - не помогло.

Изменено пользователем Edward Tarasov
Ссылка на комментарий

Рекомендуемые сообщения

  • 0

Доброго времени суток. Столкнулся с такой же проблемой в 10.4.2. В стандартном примере все работает, а в мигрированном приложении из 10.3.3 - приложение всегда ловит отмену запроса на фото. Я так понимаю где-то не хватает прав для временного файла. 

Путем долгих и мучительных экспериментов и курением доки организовал эту всю штуку через нативные интенты.

Код вырезан из рабочего проекта, по этому извините если что-то не так. Но смысл должен быть понятен.

Здесь кроме самого фото еще реализовано автоматическое поворачивание картинки по Exif-даным, относительно того в каком положении был телефон.

Так же очень важно не забыть выставить права в опциях приложение и подключить Secure File Sharing в Entitlement List. С Uses секцией надеюсь разберетесь, не уверен что нужно для Вашей задачи все из того что я кинул.

Uses 
  ....
    Androidapi.JNI.GraphicsContentViewText,
  Androidapi.JNI.App,
  Androidapi.JNI.JavaTypes,
  Androidapi.Helpers,
  FMX.Platform.Android,
  System.Permissions,
  Androidapi.JNI.Os,
  Androidapi.JNI.Net,
  Androidapi.JNI.Support,
  Androidapi.JNI.Provider,
  Androidapi.JNIBridge,
  FMX.Helpers.Android,
  FMX.Surfaces,
  Androidapi.JNI.Media;

  TfmMain = class(TForm)
     ...
    procedure FormCreate(Sender: TObject);
    procedure btnPhotos_ShowCameraClick(Sender: TObject);
    ...
  protected
    FMessageSubscriptionID : integer;
    FPermissionWriteExternalStorage: string;
    FPermissionCamera: string;
    FPermissionReadExternalStorage: string;

    FphotoUri :Jnet_Uri;
    JFileName: JFile;
	
    procedure DisplayRationale(Sender: TObject; const APermissions: TArray<string>; const APostRationaleProc: TProc);
    procedure TakePicturePermissionRequestResult(Sender: TObject; const APermissions: TArray<string>; const AGrantResults: TArray<TPermissionStatus>);
    procedure TakePicturePermissionRequestAfterINitResult(Sender: TObject; const APermissions: TArray<string>; const AGrantResults: TArray<TPermissionStatus>);

    procedure HandleActivityMessage(const Sender: TObject; const M: TMessage);
    function OnActivityResult(RequestCode, ResultCode: Integer; Data: JIntent): Boolean;
  end;

procedure TfmMain.FormCreate(Sender: TObject);
begin
  FPermissionCamera := JStringToString(TJManifest_permission.JavaClass.CAMERA);
  FPermissionReadExternalStorage := JStringToString(TJManifest_permission.JavaClass.READ_EXTERNAL_STORAGE);
  FPermissionWriteExternalStorage := JStringToString(TJManifest_permission.JavaClass.WRITE_EXTERNAL_STORAGE);
  ...
end;

procedure TfmMain.HandleActivityMessage(const Sender: TObject; const M: TMessage);
begin
  if M is TMessageResultNotification then begin
    OnActivityResult(TMessageResultNotification(M).RequestCode, TMessageResultNotification(M).ResultCode, TMessageResultNotification(M).Value);
  end;
end;

function TfmMain.OnActivityResult(RequestCode, ResultCode: Integer;  Data: JIntent): Boolean;
  procedure SetPhotoData();
  var
    jBmp : JBitmap;
    xSurface : TBitmapSurface;

    vImage : TImage;

    xExif : JExifInterface;
    sOrientation : JString;
    rotationAngle, orientation : integer;
    sFile : string;

    ScreenService: IFMXScreenService;
  begin
    if RequestCode = 1001 then begin
      if ResultCode = TJActivity.JavaClass.RESULT_OK then begin
        if FphotoUri <> nil then begin
          jBmp := TJImages_Media.JavaClass.getBitmap(SharedActivity.getContentResolver, FphotoUri);
          if jBmp <> nil then begin
            xSurface := TBitmapSurface.Create;
            try
              JBitmapToSurface(jBmp, xSurface);
              vImage := TImage.Create(nil);

              try
                vImage.Bitmap.Assign(xSurface);

                sFile := JStringToString(JFileName.getAbsolutePath);
                xExif := TJExifInterface.JavaClass.init(StringToJString(sFile));

                sOrientation := xExif.getAttribute(TJExifInterface.JavaClass.TAG_ORIENTATION);
                if sOrientation = nil then
                  orientation := TJExifInterface.JavaClass.ORIENTATION_NORMAL
                else
                  orientation := StrToIntDef(JStringToString(sOrientation), 0);

                rotationAngle := 0;

                if orientation = TJExifInterface.JavaClass.ORIENTATION_ROTATE_90 then
                  rotationAngle := 90;
                if orientation = TJExifInterface.JavaClass.ORIENTATION_ROTATE_180 then
                  rotationAngle := 180;
                if orientation = TJExifInterface.JavaClass.ORIENTATION_ROTATE_270 then
                  rotationAngle := 270;

                if rotationAngle <> 0 then
                 vImage.Bitmap.Rotate(rotationAngle);

                //Готовое фото уже в vImage - выводим куда нужно
                imPhotos_Photo.Bitmap.Assign(vImage.Bitmap);
              finally
               vImage.Free;
              end;
            finally
              xSurface.Free
            end{try..finally};
          end else begin
            //не вдалось завантажити картинку
            TDialogService.ShowMessage('Не вдалось завантажити картинку');
          end{if..else};
        end else begin
          //пустий Uri
          TDialogService.ShowMessage('Пустий Uri');
        end{if..else};
      end else begin
        TDialogService.ShowMessage('Відмовились робити фото');
      end{if..else};
    end{if};
  end;

begin
  Result := False;

  TMessageManager.DefaultManager.Unsubscribe(TMessageResultNotification, FMessageSubscriptionID);
  FMessageSubscriptionID := 0;

  if RequestCode = 1001 then begin
	  // робота з камерою - отримання фото
    SetPhotoData();

	exit;
  end;
  ...
end;


procedure TfmMain.TakePicturePermissionRequestResult(Sender: TObject;
  const APermissions: TArray<string>;
  const AGrantResults: TArray<TPermissionStatus>);
var
  intent : jintent;
  Authority: JString;
begin
  // 3 permissions involved: CAMERA, READ_EXTERNAL_STORAGE and WRITE_EXTERNAL_STORAGE
  if (Length(AGrantResults) = 3) and (AGrantResults[0] = TPermissionStatus.Granted) and (AGrantResults[1] = TPermissionStatus.Granted) and (AGrantResults[2] = TPermissionStatus.Granted) then begin
    //створюємо "намір" отримання фото з камери
    intent := TJIntent.JavaClass.init;
    intent.setAction(TJMediaStore.JavaClass.ACTION_IMAGE_CAPTURE);

    //створюємо тимчасовий файл
    JFileName := TJFile.JavaClass.createTempFile(StringToJString('picture'), StringToJString('.jpg'));
    //отримуємо опис прав по файлам
    Authority := StringToJString(JStringToString(TAndroidHelper.Context.getApplicationContext.getPackageName) + '.fileprovider');
    //отримуємо URI-до тимчасового файлу в контексті нашої аплікації
    FphotoUri:= TJFileProvider.JavaClass.getUriForFile(TAndroidHelper.Context, Authority, JFileName);
    //кажемо що наш "намір" має писати дані в цей тимчасовий файл
    intent.putExtra(TJMediaStore.JavaClass.EXTRA_OUTPUT,
                    TJParcelable.Wrap((FphotoUri as ILocalObject).GetObjectID)
                   );
    //реєструємось на отримання подій
    FMessageSubscriptionID := TMessageManager.DefaultManager.SubscribeToMessage(TMessageResultNotification, HandleActivityMessage);
    //стартуємо наш "намір"
    MainActivity.startActivityForResult(intent, 1001);
  end else
    TDialogService.ShowMessage('Не надані необхідні для роботи дозволи!');
end;

procedure TfmMain.DisplayRationale(Sender: TObject;
  const APermissions: TArray<string>; const APostRationaleProc: TProc);
var
  I: Integer;
  RationaleMsg: string;
begin
  for I := 0 to High(APermissions) do
  begin
    if APermissions[I] = FPermissionCamera then
      RationaleMsg := RationaleMsg + 'The app needs to access the camera to take a photo' + SLineBreak + SLineBreak
    else if APermissions[I] = FPermissionReadExternalStorage then
      RationaleMsg := RationaleMsg + 'The app needs to read a photo file from your device';
  end;

  // Show an explanation to the user *asynchronously* - don't block this thread waiting for the user's response!
  // After the user sees the explanation, invoke the post-rationale routine to request the permissions
  TDialogService.ShowMessage(RationaleMsg,
    procedure(const AResult: TModalResult)
    begin
      APostRationaleProc;
    end);
end;

procedure TfmMain.btnPhotos_ShowCameraClick(Sender: TObject);
begin
  PermissionsService.RequestPermissions( [FPermissionCamera, FPermissionReadExternalStorage, FPermissionWriteExternalStorage],
                                         TakePicturePermissionRequestResult,
                                         DisplayRationale
                                       );
end;

P.S. возможно нужно будет вставить в манифест:

  android:requestLegacyExternalStorage="true"

 

Изменено пользователем Freezer_86
Ссылка на комментарий

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить на вопрос...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу
×
×
  • Создать...