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

Freezer_86

Пользователи
  • Постов

    8
  • Зарегистрирован

  • Посещение

Посетители профиля

Блок последних пользователей отключён и не показывается другим пользователям.

Достижения Freezer_86

  1. Доброго времени суток. Столкнулся с такой же проблемой в 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"
  2. Это не очень относиться к теме но оставлю это здесь, вдруг кому пригодиться. В моей задаче нужно было еще отслеживать на какой странице находиться пользователь, а как оказалось свойство URL тоже работает некорректно. Пришлось "накостылять" следующее: В WebBrowser.Android.pas добавляем: function TAndroidWebBrowserService.originalUrl: string; begin if FJWebBrowser = nil then Result := FURL else Result := JStringToString(FJWebBrowser.getOriginalUrl); end; В WebBrowser.Win.pas добавляем: function TWindowsWebBrowserService.LocationUrl: string; begin Result := FUrl; if FInstance <> nil then Result := FInstance.LocationURL; end; В WebBrowser.pas изменим: function TKCustomWebBrowser.GetURL: string; begin if (csDesigning in ComponentState) or (FWeb = nil) then Result := FURL else {$IFDEF MSWINDOWS} Result := (FWeb as TWinWBMediator).WB.LocationUrl; {$ELSE} Result := (FWeb as TAndroidWebBrowserService).originalUrl {$ENDIF} end; Как результат - корректная работа панели навигации.
  3. Натыкался на такую проблему, смог обойти написанием своей копией TWebBrowser. Основное изменение для обхода именно ошибки с CoboBox'ом это в начале процедуры TCustomWebBrowser.FormHandleCreated вставкой кода: {$IFDEF MSWINDOWS} exit; {$ENDIF} После этого никаких проблем с пересозданием. Правда у меня все браузера создаются в Runtime. Не знаю или это подойдет для нормальной работы с загрузкой из DFM.
  4. Как оказалось - проблемы были в самой Delphi. После обновления на 10.2.1 - тот же код работает без каких либо проблем.
  5. Как я вижу есть несколько возможных причин: неверный формат данных, неверная реализация TGrid под Android, неподдерживаемая комбинация компонентов, ошибки в моем коде реализации (что маловероятно поскольку кода почти нет, Live Binding). Неужели никто не сталкивался с подобными проблемами?
  6. не пробовал, но если на Windows все ок, значит TBitmap коректный. Или не всегда? Подготовил тестовый проект который иллюстрирует проблему: GridBlobTest.rar
  7. Пишу кроссплатформенное приложение. Результат поиска отображается в TGrid. Стал вопрос отображения картинки в одной из колонок. На Windows все ок, но на планшете происходят просто чудеса: при первом отображение все корректно, но если простоколить вверх-вниз как картинки одни перетираются другими, часть вообще отображается вверх ногами. Код для сохранение картинки(jpg) в базу: if Assigned(sm) then begin sm.Position := 0; //TBlobField(dmData.cdsPlayerData.FieldByName('Photo')).LoadFromStream(sm); vImage := TImage.Create(nil); try sm.Position := 0; vImage.Bitmap.LoadFromStream(sm); vKoef := vImage.Bitmap.Height / 64; vImage.Bitmap.Resize(Trunc(vImage.Bitmap.Width / vKoef), Trunc(vImage.Bitmap.Height / vKoef)); sm.Free; sm := TMemoryStream.Create(); try vImage.Bitmap.SaveToStream(sm); TBlobField(dmData.cdsPlayerData.FieldByName('SmallPhoto')).LoadFromStream(sm); finally sm.Free; end; finally vImage.Free; end; end{if}; До скрола: После скрола: Пробовал и LiveBinding, и ручную прорисовку - результат один и тот же. Есть идеи что не так? P.S. Знаю что нужно делать через TListView, но заказчик хочет «сеточку как в старой программе», так как на android будет работать только на планшетах – я согласился.
×
×
  • Создать...