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

Евгений Корепов

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

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

  • Посещение

  • Победитель дней

    100

Весь контент Евгений Корепов

  1. TidHTTPClient перестал работать в Android 6. При попытке Get приложение закрывается с segmentation fault. То же самое приложение на всех остальных версиях андроида работает нормально. На эмуляторе проверить не удалось, по какой то причине эмулятор с андроид 6 у меня запускается около часа, а попытка отладки приводит к зависанию дельфи. Взял на пол часа живое устройство, отладка показала что крах происходит на стадии разбора результата. Т.е. данные с сервера реально получает (это подтверджают логи сервера), и при попытке вернуть результат все умирает. Код простой: Var HTTPResult : TStringStream; URI: TIdURI; HTTP: TIdHTTP; begin AURL:='http://10.10.0.1'; FHost:='10.0.0.1'; HTTP:=TIdHTTP.Create; HTTP.CookieManager := TIdCookieManager.Create(HTTP); HTTP.Request.Host:=FHost; HTTP.AllowCookies := true; HTTP.HandleRedirects := True; HTTP.ConnectTimeout:=6000; HTTP.ReadTimeout:=30000; HTTP.Request.CustomHeaders.AddValue('Connection','keep-alive'); HTTP.Request.Accept:='text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8'; HTTP.Request.UserAgent:='Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.152 Safari/537.36'; HTTP.Request.AcceptEncoding:='gzip, deflate, sdch'; HTTP.Request.AcceptLanguage:='ru,en-US;q=0.8,en;q=0.6'; Result.Status:=False; Result.MessageText:=''; AURL:=StringReplace(AURL,'{AuthorizationKey}',AuthorizationKey,[]); AURL:=StringReplace(AURL,'{Host}',FHost,[]); HTTPResult:= TStringStream.Create('', TEncoding.UTF8); URI := TIdURI.Create(AURL); HTTP.CookieManager.AddServerCookie(CookieAuthorization, URI); try HTTP.Get(AURL,HTTPResult); except on E : Exception do begin Result.Status:=False; Result.MessageText:=E.Message; Exit; end; end; Result.Status:=True; Result.MessageText:=Trim(HTTPResult.DataString); HTTPResult.Free; URI. Free; end; Падает на строке HTTP.Get(AURL,HTTPResult);, try не срабатывает. Запрос именно http, не https. К сожалению живое устройство было у меня не долго, досконально разобраться не успел. Выяснил что падает на строке 1423 в idHTTP.pas: IOHandler.ReadStream(LS, -1, True); У кого будут какие мысли? Понятно что разработчики забили на Indy довольно давно, но не хочется целиком десяток проектов переписывать. P.S. System.Net.HTTPClient работает в тех же условиях, не падает, но не смог заставить работать cookie, разбираюсь в чем дело. Хотя при отсутствии таймаутов и обработки редиректов применение сего очень ограничено.
  2. Спасибо огромное! В прошлом не хватало OnBalloonClick. Один вопрос - картинка берется из приложения? Вот свою бы ставить на выбор. И OnAnimate не задействовано никак. Развитие компонента ожидается?
  3. Избежать появления кнопки Вставить можно очисткой буфера обмена. Например так: procedure TFormMain.Edit1CanFocus(Sender: TObject; var ACanFocus: Boolean); begin if Assigned(FClipboardSvc) then FClipboardSvc.SetClipboard(''); ACanFocus:=True; end; Обратите внимание что именно пустая строка очищает буфер, попытка сделать FClipboardSvc.SetClipboard(Nil); поместит в буфер строку 'empty'.
  4. Вы будете смеяться, но проблема решена. Методом научного тыка. Не работающая установка значения ListView.ScrollViewPos решается следующей строкой ListView.ItemIndex:=0; (Не важно 0 или любое другое число). Т.е. для того чтоб заработало делаем так: ListView.ItemIndex:=0; ListView.ScrollViewPos:=333; // Ура, работает!!! Почему так работает, я не понял.
  5. Ветка форума поэтому и называется TListView, что речь идет о TListView, а не ListBox. Кстати заметил странность, после ListView.Resize иногда GetMaxScrollViewPos выдает реальное число а не 0. Удалось точно узнать в какой ситуации: 1. Добавляем много итемов, чтоб не помещались в видимую область 2. Удаляем все итемы (ListView.ClearItems;) 3. Опять добавляем итемы и позиционируем ScrollViewPos:=300 - Ура все работает. Если в 1 пункте все итемы помещаются в видимую область, то в Четвертом пункте ScrollViewPos:=300 не приводит ни к какому результату (GetMaxScrollViewPos = 0). Остается списать все на очередной косяк Embarcadero, других мыслей нет...
  6. Вот здесь посмотрите https://code.google.com/p/delphi-foundations/source/browse/trunk/Book/06.+Arrays,+collections+and+enumerators/Simple+search+%28TArray+class+helper%29/CCR.Generics.SimpleArraySearch.pas?r=29
  7. Не подходит. ScrollTo позиционирует Item по нижней границе ListView. Трудно придумать применение этой функции с точки зрения дизайна приложения. Логично позиционировать по верху. Но если высота ListView не кратна ItemHeight, то даже с помощью дополнительных вычислений не возможно этим методом позиционировать нужный итем сверху. Метод ScrollViewPos идеален для этого, но по какой то причине не работает сразу после создания итемов.
  8. Задача в следующем: Динамически заполняю ListView, после заполнения нужно установить ListView.ScrollViewPos в произвольную позицию. Но не выходит по причине того, что в процедуре TCustomListView.SetScrollViewPos(const Value: Single) функция GetMaxScrollViewPos всегда в таком случае возвращает ноль. Подозреваю что после добавления итемов нужно как то передёрнуть ListView, но не знаю как. Пробовал ApplyStyleLookup, Repaint, Resize, RecalcSize - не помогает. Отрисованный и видимый в приложении ListView прекрасно позиционируется с помощью ScrollViewPos. А GetMaxScrollViewPos выдает реальную длину списка. Ткните меня в правильную процедуру.
  9. Думаю да, судя по исходникам под все платформы. И кстати ошибка у меня в коде: Note: FindFirst allocates resources (memory) that must be released by calling FindClose. Забыл FindClose.. В хелпе есть упоминание мака, так что думаю будет работать точно. Note: Some of the file attribute constants are not valid on all platforms. For example, faVolumeID and faArchive do not work on MAC OS.
  10. Ура! Я победил проблему. Причем с помощью почти забытой мной процедуры FindFirst ;-) Код работает корректно под Windows и Android. Файл не передергивается, антивирус спокоен. function TFileManager.GetFileSize(APath : String) : String; Var AFileSizeByte : Int64; AFileSizeFloat : Double; SearchRec : TSearchRec; FileAttrs: Integer; begin FileAttrs :=faArchive; FileAttrs := FileAttrs + faAnyFile; Result:='unknow'; AFileSizeByte:=0; try FindFirst(APath,FileAttrs,SearchRec); AFileSizeByte:=SearchRec.Size; FindClose(SearchRec); except Exit; end; if AFileSizeByte<1024 then begin Result:=Format('%d',[AFileSizeByte])+' Byte'; Exit; end; if AFileSizeByte<1048576 then begin AFileSizeFloat:=AFileSizeByte/1024; Result:=Format('%6.3f',[AFileSizeFloat])+' KByte'; Exit; end; if AFileSizeByte<1073741824 then begin AFileSizeFloat:=AFileSizeByte/1048576; Result:=Format('%6.3f',[AFileSizeFloat])+' MByte'; Exit; end; AFileSizeFloat:=AFileSizeByte/1073741824; Result:=Format('%6.3f',[AFileSizeFloat])+' GByte'; end;
  11. Эффект тот же. Этот способ я вторым проверил.
  12. Нужно получить размер файла под любыми платформами. Сейчас использую функцию function TFileManager.GetFileSize(APath : String) : String; Var F : file of Byte; AFileSizeByte : Integer; AFileSizeMbyte : Double; begin Result:=''; AssignFile(F, APath); FileMode := 0; // readonly try try Reset(F); AFileSizeByte:=FileSize(F); CloseFile(f); except end; finally AFileSizeMbyte:=AFileSizeByte/1048576; Result:=Format('%6.3f',[AFileSizeMbyte])+' Mbyte'; end; end; Работает, но есть одно но - под Windows, если проверяю exe файл, антивирус (в данном случае Защитник Windows) унюхивает что производится открытие файла и начинает его проверять на вирусы. Из за этого сканирование директории с большим количеством исполняемых файлов подвешивает основной поток приложения. Вопрос в следующем - нет ли другого способа получения размера? Странно что TFile, TPath или TDirectory не содержат такого полезного метода. В данный момент двигаюсь в направлении отдельного потока получения размера, но решение не красивое, хочется быстро и сразу.
  13. Без "FloatAnimation.Parent:=Nil" вылетало исключение. Какой именно не скажу, грохнул весь этот код. Опять наступил на старые грабли и изменил принципу "Никогда, никогда не использовать ListBox в проектах". Самодельный аналог на вертикальном скроллбоксе работает на порядок красивее и стабильнее. Этот компонент переписал на ListView.
  14. Задача следующая - добавить анимацию в ListBoxItem по клику, ListBoxItem может быть несколько десятков. Создавать для каждого Animation накладно. Update: Нашел решение в теме http://fire-monkey.ru/topic/1073-smena-roditelskogo-komponenta-dlia-animatora/ : но мне нужно также событие AnimationFinish, по нему происходит смена содержимого ListBox. (Пишу компонент файл-менеджера для одного проекта). Update: Вроде нашел решение, все работает. Подскажите корректно ли я это делаю? procedure TFormMain.FormCreate(Sender: TObject); begin FloatAnimation.Parent:=Nil; // FloatAnimation создан в дизайнатйме, лежит на форме, поэтому нужно так сделать. FloatAnimation.Enabled:=False; end; procedure TFormMain.ListBoxFilesItemClick(const Sender: TCustomListBox; const Item: TListBoxItem); begin CurrentItem:=Item; if CurrentItem.Tag=1 then // Смена папки begin FloatAnimation.Parent:=Item; FloatAnimation.PropertyName:='Opacity'; FloatAnimation.Enabled:=True; FloatAnimation.Start; end; end; procedure TFormMain.FloatAnimationFinish(Sender: TObject); begin FloatAnimation.Enabled:=False; FloatAnimation.Parent:=Nil; FillListBoxFile(CurrentItem.TagString); end; Причем без этого куска кода: FloatAnimation.Enabled:=False; FloatAnimation.Parent:=Nil; работать не хочет. Хотя работает и ладно... ;-)
  15. { "registration_ids": [ "APA91bFwDgtPtlwgvbgVt7qpxqes0UIi...", "APA91bFS3fknVDY6qifQiJ1KZDSjwZE..." ], "data": { "title": "Заголовок сообщения", "message": "Текст сообщения" } }
  16. Подскажите где закралась ошибка. Процедура должна отправлять файл через намерение (файл текстовый). aFileName:='/storage/emulated/0/Download/test/тестовый файл для отправки.out.txt'; aComment:='Комментарий к файлу'; procedure ShareFile(aFileName, aComment : String); var Intent : JIntent; uri : Jnet_Uri; AttachmentFile: JFile; begin Intent := TJIntent.Create; Intent.setAction(TJIntent.JavaClass.ACTION_SEND); Intent.setFlags(TJIntent.JavaClass.FLAG_ACTIVITY_NEW_TASK); Intent.putExtra(TJIntent.JavaClass.EXTRA_SUBJECT, StringToJString(aComment)); Intent.putExtra(TJIntent.JavaClass.EXTRA_TEXT, StringToJString(aComment)); AttachmentFile := TJFile.JavaClass.init(StringToJString(aFileName)); Uri := TJnet_Uri.JavaClass.fromFile(AttachmentFile); Intent.putExtra(TJIntent.JavaClass.EXTRA_STREAM, TJParcelable.Wrap((Uri as ILocalObject).GetObjectID)); Intent.setType(StringToJString('text/plain')); SharedActivity.startActivity(Intent); end; Наблюдаю следующее: Gmail - все отлично, файл присоединён, комментарий в теме письма DropBox - все отлично, файл передан Google Drive - файл передан, но у него отрезано расширение (в папке лежит файл с именем "тестовый файл для отправки") Yandex Disk - все работает Облако Mail.ru - предлагает создать текстовый файл ("Новый текстовый файл.txt"), в который записывает только две одинаковые строчки "Комментарий к файлу" Уже весь мозг сломал. А заказчик требует работу через все эти системы.
  17. Да, точно. Дезинформировал в прошлом посте. У меня вот так: implementation {$IFDEF ANDROID} uses FMX.PushNotification.Android; Var APushService : TPushService; AServiceConnection : TPushServiceConnection; {$ENDIF ANDROID}
  18. В uses должно быть только System.PushNotification. В опциях проекта отметили Receive push notifications?
  19. Огромное спасибо!!! Все заработало! Проблема видимо в косячном примере от embarcadero. Проверку InAppPurchase.IsProductPurchased(ProductId) необходимо выполнять в событии OnProductsRequestResponse, т.е. после завершения ,видимо ассинхронного, InAppPurchase.QueryProducts. А никак не в OnSetupComplete как в примере от Embarcadero "CapitalIAP". Кстати в Delphi 10 тот же косяк в примере, видимо они даже не пробовали проверять его работоспособность.
  20. Купил сам у себя, не через тестовый аккаунт. Деньги списались,в "Payments Merchant Center" покупка отобразилась. Но FInAppPurchase.IsProductPurchased(NoAdsID) мне говорит False, не куплен продукт. Что делать, ума не приложу.
  21. InAppPurchase.IsProductPurchased работает на тестовых аккаунтах? Сделал покупку, но IsProductPurchased всегда возвращает False. procedure TFormMain.InAppPurchaseSetupComplete(Sender: TObject); begin LogMy('InAppPurchaseSetupComplete'); FInAppPurchase.QueryProducts; if FInAppPurchase.IsProductPurchased(NoAdsID) then begin LogMy(NoAdsID+' Yes ProductPurchased'); Буду очень благодарен, если кто даст ссылку на нормальную документацию, желательно на русском. Хочется понять хотя бы основные вещи, к примеру что такое метод ConsumeProducts (потреблять продукты?). И возможна ли отладка InAppPurchase? Запуск в отладочной версии не позволяет работать с InAppPurchase.
  22. Virtual Keboard как раз есть и видима. Так что не вариант. Кстати события OnVirtualKeyboardHidden и OnVirtualKeyboardShown в XE8 работают не стабильно, иногда с секундными задержками, иногда вообще забывают срабатывать. Видимость лучше проверять с помощью function TFormMain.KeyboardVisible : Boolean;var Keyboard: IFMXVirtualKeyboardService; begin Result:=False; if TPlatformServices.Current.SupportsPlatformService( IFMXVirtualKeyboardService, IInterface( Keyboard ) ) then Result:=TVirtualKeyboardState.Visible in Keyboard.GetVirtualKeyBoardState; end;
  23. Delphi XE8, Android. Возможно ли определить источник ввода символов в TEdit? Т.е. откуда приходит ввод - виртуальная клавиатура или внешняя usb или блютус клавиатура (в моём случае это сканеры штрих кодов)
  24. Var HDevicePushParams : TDevicePushParams; APushService : TPushService; AServiceConnection : TPushServiceConnection; SQuery : String; begin APushService:=TPushServiceManager.Instance.GetServiceByName(TPushService.TServiceNames.GCM); APushService.AppProps[TPushService.TAppPropNames.GCMAppID]:='ХХХХХХХХХХХХХХХХ'; AServiceConnection:=TPushServiceConnection.Create(APushService); AServiceConnection.Active:=True; AServiceConnection.OnChange:=ServiceConnectionOnChange; AServiceConnection.OnReceiveNotification:=ServiceConnectionOnReceiveNotification; HDevicePushParams.DeviceID:=APushService.DeviceIDValue[TPushService.TDeviceIDNames.DeviceID]; HDevicePushParams.DeviceToken:=APushService.DeviceTokenValue[TPushService.TDeviceTokenNames.DeviceToken]; SQuery:=APIURL+'?DeviceID='+HDevicePushParams.DeviceID+'&DeviceToken='+HDevicePushParams.DeviceToken; HTTPThread:=THTTPThread.Create(SQuery,FQueue); // Здесь просто отправка на сервер в потоке. Сервер принимает стоку и складывает в базу пары "DeviceID - DeviceToken", можно еще что нибудь отправлять, чтоб точно идентифицировать клиента. А на сервере все еще проще. Вот php: $title = 'Это заголовок'; $message = 'Это текст сообщения.' $devices = 'DeviceToken - один конкретный получатель'; $apiKey = "AIzaХХХХХХХХХХХХХХХХХХХХХХХХХХХХХХХХХХХХ"; $gcpm = new GCMPushMessage($apiKey); $gcpm->setDevices($devices); $response = $gcpm->send($message, array('title' => $title)); Лениво было писать велосипед, использовал готовую отсылалку https://github.com/mattg888/GCM-PHP-Server-Push-Message . Там все просто, она заворачивает все в json и отправляет на http
  25. Delphi XE8, Android. Пишу слайдер картинок. Задачу себе поставил аналогичную слайдеру Ввконтакте. Т.е. Жестами листаем налево/направо, двойной клик увеличение, повторный двойной клик уменьшение, ну и пальцами можно растягивать изображения. Все работало замечательно до момента добавления анимации. Слайд (TImage) лежит в TScrollBox. Анимация увеличения (FloatAnimation) тоже отлично работает. Но позиционирование картинки сделать не могу с анимацией, анимацию не могу привязать к ViewportPosition. В итоге, при увеличении картинки, не область по которой ткнули, а по уродски - левый верхний угол остаётся зафиксированным, увеличивается вправо и вниз. Как можно связать FloatAnimation и ViewportPosition ?
×
×
  • Создать...