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

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

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

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

  • Посещение

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

    102

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

  1. Вот https://play.google.com/intl/ru/about/monetization-ads/payments/ Платежи Приложения, через которые можно делать покупки, должны соответствовать следующим требованиям: Покупки в магазине. Плата за приобретение и скачивание приложений в Google Play должна взиматься через систему оплаты Google Play. Покупки через приложение. Для продажи цифровых продуктов через игру, представленную в Google Play, необходимо использовать систему оплаты контента Google Play. При продаже цифровых продуктов через другие виды приложений, представленные в Google Play, необходимо также использовать систему оплаты контента Google Play. Исключения составляют следующие случаи: продажа нецифровых товаров; продажа цифрового контента, который может использоваться вне приложения (например, треков, которые можно воспроизводить в других проигрывателях). Виртуальную валюту можно использовать только в приложении, через которое она была приобретена. Запрещается вводить пользователей в заблуждение относительно приложений, а также услуг, товаров, контента и функций, которые можно через них приобрести. Если за доступ к функциям, указанным в описании приложения в Google Play, взимается плата, вы обязаны предупредить об этом пользователей. Удивительно если бы было по другому. Не думаю что Гугль откажется от своих 30% от продаж.
  2. Вот тут прочтите https://developer.android.com/google/play/billing/api.html#consume . Вам нужен потребляемый продукт. К примеру пользователь купил продукт, пусть будут самоцветы InAppPurchase.PurchaseProduct(PProductId); после этого вы записываете что у пользователя есть 100 самоцветов внутри (или где то еще) своего приложения. Теперь сообщаете билингу гугля что пользователь потребил продукт (ведь самоцветы у него уже его) : InAppPurchase.ConsumeProduct(PProductId); Все, билинг гугля готов вам продать этот товар (100 спмоцветов) еще раз. P.S. За применение АПИ Робокасса и подобного, согласно правилам, в лучшем случае вы получите заблокированное приложение, в худшем случае вы лишитесь аккаунта разработчика.
  3. Кнопка "Добавить в избранное" и соответственно раздел Избранное в профиле очень помогли бы в работе с форумом. Добавлять в избранное хочется отдельные посты. Потому как поиск работает плохо и искать когда то попавшееся на глаза нужное решение найти проблематично.А так бы ткнул на Добавить в избранное, по мере надобности зашел в свое Избранное, увидел разбитое по разделам форума списки избранного и нашел что нужно. Заранее благодарю!
  4. Ответ уже есть на форуме в ветке пуша, поищите.
  5. Блестящая работа! Простой и красивый код! Потеря пакетов обусловлена (скорее всего) статичным buffer_size, на разных устройствах он может быть разным и правильнее его размер получать вот так buffer_size:= TJAudioTrack.JavaClass.getMinBufferSize(PSampleRateHz, TJAudioFormat.JavaClass.CHANNEL_OUT_MONO, TJAudioFormat.JavaClass.ENCODING_PCM_16BIT); if (buffer_size = TJAudioTrack.JavaClass.ERROR) then Exit; if (buffer_size = TJAudioTrack.JavaClass.ERROR_BAD_VALUE) then Exit; Еще конечно бы двойную буферизацию для записи/воспроизведения Так же можно сразу запустить проигрывание audiotrack.play в FormCreate, реальные звуки будут проигрываться и так: procedure TForm1.ServerUDPRead(AThread: TIdUDPListenerThread; const AData: TIdBytes; ABinding: TIdSocketHandle); begin audiotrack.write(TBytesToTJavaArray(TBytes(AData)),0,Length(AData)); end;
  6. Вот, если поможет. Стабильно работающий в одном из проектов код. Для получения строки с сервера используется FIdTCPClient.IOHandler.ReadLnWait - там уже есть все что нужно, что бы получить строку с сервера в течении FIdTCPClient.ReadTimeout:=constReadTimeout (милисекунды). procedure TTCPThread.CreateNetwork; begin FIdTCPClient:=TIdTCPClient.Create(Nil); FIdTCPClient.Host:=FInstance.Host; FIdTCPClient.Port:=FInstance.Port; FIdTCPClient.ConnectTimeout:=constConnectTimeout; //100ms FIdTCPClient.ReadTimeout:=constReadTimeout; //100ms end; procedure TTCPThread.SendCommand(const ACommand : TCommand; var AThreadResult : TThreadResult); begin if Not FIdTCPClient.Connected then try FIdTCPClient.Connect; except on E:Exception do begin AThreadResult.Error:=True; AThreadResult.ErrorMessage:=E.Message; exit; end; end; if FIdTCPClient.Connected then begin try FIdTCPClient.Socket.WriteLn(ACommand.CommandString); except on E:Exception do begin AThreadResult.Error:=True; AThreadResult.ErrorMessage:=E.Message; exit; end; end; try AThreadResult.JSONString:=FIdTCPClient.IOHandler.ReadLnWait; except on E:Exception do begin AThreadResult.Error:=True; AThreadResult.ErrorMessage:=E.Message; exit; end; end; AThreadResult.JSONString:=AThreadResult.JSONString.Trim; end else begin AThreadResult.Error:=True; AThreadResult.ErrorMessage:='Not connected'; end; end; Синхронизация с основным потоком: procedure TTCPThread.Execute; Var ACommand : TCommand; AThreadResult : TThreadResult; begin while Not Terminated do if FQueueRequest.PopItem(ACommand) = TWaitResult.wrSignaled Then begin AThreadResult.Error:=False; AThreadResult.ErrorMessage:=''; AThreadResult.Process:=ACommand.Process; AThreadResult.Command:=ACommand.Command; AThreadResult.CommandName:=ACommand.CommandName; AThreadResult.JSONString:=''; SendCommand(ACommand, AThreadResult); if Assigned(FOnReceiveData) then TThread.Synchronize(Self, procedure begin FOnReceiveData(Self, AThreadResult); end); if AThreadResult.Error then while FQueueRequest.PopItem(ACommand) = TWaitResult.wrSignaled do begin end; end; end;
  7. procedure TFormMain.GetHTTP(ACommand : String; AIndex : Integer = -1; AImageURL : String = ''); Var AHTTPRec : THTTPRec; AFileName : String; begin FAppStage:='GetHTTP '+ACommand+' start'; AHTTPRec.Query:=''; AHTTPRec.CachePath:=''; AHTTPRec.ErrorMsg:=''; AHTTPRec.ErrorCode:=0; {SKIP CODE} if ACommand=CommandRegisterFCM then begin if Setting.RegionCode.IsEmpty then Exit; AHTTPRec.Query:=APIURL+'?cmd='+ACommand+'&region='+Setting.RegionCode+ '&DeviceID='+HDevicePushParams.DeviceID+'&DeviceToken='+HDevicePushParams.DeviceToken+'&AppVer='+AppVersion; if Setting.SettingState.AllNotification then AHTTPRec.Query:=AHTTPRec.Query+'&AllNotification=1' Else AHTTPRec.Query:=AHTTPRec.Query+'&AllNotification=0'; end; {SKIP CODE} FQueueRequest.PushItem(AHTTPRec); //Заталкиваем данные в FQueueRequest: TThreadedQueue<THTTPRec> - передаем данные в отдельный поток для отправки запроса FAppStage:='GetHTTP stop '+ACommand; end; Вот что в этой функции - подготавливаем все нужные данные для моего сервера PUSH на PHP и отправляем в очередь для потока который их отправит как освободится от других задач. THTTPRec=record Command : String; //Текущая команда Query : String; //Запрос в виде http://url CachePath : String; //Путь для хранения кеша полученных данных ErrorMsg : String; //Результатт в текстовом виде ErrorCode : Integer; //Результат в числовом виде JSON : TJSONObject; // MemoryStream : TMemoryStream; // Bitmap : TBitmap; BitmapSurface : TBitmapSurface; // ListItemImage : TListItemImage; // ListItemImage : TBitmap; ImageIndex : Integer; FromCache : Boolean; end; THTTPRec служит для обмена данными с HTTP потоком - отправляем данные потоку и получаем данные из потока
  8. Сервер просто заменит вас, т.е. его функция хранение идентификаторов устройств (если нужно) и токенов. И вы его заставите делать тоже самое что и вы сейчас - запомнить токен и отправить сообщение с помощью него (но уже через АПИ FireBase). В FireBase есть отладка пушсообщений, она вам что то показывает? И еще вопрос - приложение у вас опубликовано в маркете?
  9. Бывает что после настройки Firebase изменения не сразу проходят в недрах гугля, иногда через пару дней только все начинает работать. Не знаю как сейчас, раньше нужно было еще и опубликовать приложение в маркете, бывало что под дебаг версией не приходили сообщения, а только под релизной. Хотя могу и ошибаться, давно было, сейчас все работает - настроил и забыл...
  10. От XE7 до Tokyo, на всех работает
  11. letsencrypt.org предоставляет сертификат для сайтов и список способов их установки/обновления. Рекомендуемый это https://certbot.eff.org/ - выбираем софт, выбираем операционку и вперед. Инструкции очень подробные. Да, еще зависит от того какой уровень доступа к вашему серверу, есть доступ к шеллу или нет.На https://letsencrypt.org/getting-started/ все пошагово расписано. Будут затыки, пишите в телеграм - чем смогу помогу
  12. Я получал, получаю и буду получать ;-) Все бесплатно, срок 3 месяца, но продление полностью автоматизировано (по крону запускаешь скрипт и она сам продляет). Отличная система, рекомендую.
  13. enatechno выше привел ссылки на статьи где все расписано по полочкам.
  14. Не действительны сертификаты SSL Certificates (для web-серверов). У них все сертификаты всегда были бесплатными (поэтому их американские монстры и прижали), платная только проверка пользователя - т.е. один раз проходишь валидацию нужного тебе класса и целый год выпускаешь сертификаты бесплатно.
  15. apptethering довольно убогий (его реализация в дельфи) - написали по быстрому модную технологию и забросили. Если не ошибаюсь, за все время существования компонента ни разу он не был исправлен или доделан. Для вашего случая проще и быстрее использовать Indy (UDP сервер и клиент) - для одновременного получения клиентами сообщения отсылаете его сервером в multicast режиме на какой нибудь порт, клиенты получат его одновременно. В apptethering не знают про multicast, по крайней мере в исходниках не нашел и потоки используются только временами и не предсказуемо.
  16. Я обычно получаю сертификат в https://www.startcomca.com - самый не дорогой сервис. Сначала нужно получить Class 2 Personal Identity Validation за US$59.90, потом можно будет генерировать неограниченное количество подписей. Сервис хорош тем что предоставляет архив с подписями, инструкциями и инструментарием (остальные сервисы дадут текстовый файлик с подписью в непредсказуемом контейнере - и разбирайся сам...). Пинаю потихоньку https://kontur.ru/ca , дабы начали на территории России выдавать сертификаты Code Signing, но пока только за бугром это можно сделать.
  17. ForceQueue не работает под андроидом.
  18. О, спасибо! Значит ListItemImage.OwnsBitmap управляет типом ссылки на Bitmap - False - слабая ссылка, True нормальная ссылка. Вот почему в документации это не указать?
  19. Как в FMX Memo задать размер таба (символа с кодом #9)? По умолчанию он гигантский. Все способы из гугля оперируют или VCL Memo или win api. Нужно мультиплатформенное решение.
  20. У него на гитхабе внизу есть пометка но что за KastriFree project я не успел посмотреть, может там все есть. Под андроидом работает отлично. Давно сам хотел все в отдельном модуле оформить, но тут удачно наткнулся...
  21. PHP один из самых простых в освоении языков. Обычный интерпретатор, т.е. в большинстве случаев, выполняет код строчка за строчкой. Нет привычной отладки (хотя может и есть в каких то средах, но я программирую на php в редакторе FAR Manager), но вы всегда можете вывести значение переменной функциями echo($Переменная) , print_r($Массив) и он высыпет все вам на экран (или в консоль). Запускать скрипт php можно двумя способами Запуск в контексте веб-сервера: Вы обращаетесь к веб серверу по адресу http://www.мойсайт.ru/мой_скрипт.php - веб сервер запускает исполняемый файл php и скармливает ему ваш скрипт и параметы переданные в запросе (Get, post). Эти параметры можно получить из специальных массивов $_GET и $_POST. Запуск ручками: для отладки и всякого другого, вы можете запустить ваш скрипт в консоли (коммандной строке) под любой платформой (линукс, винда...): " php /home/test001.php". Просто попытайтесь освоить язык, он простой, нужно два часа чтоб освоить язык до уровня написания вышеприведенного мной скрипта. По теме - если у вас выводит [], то значит узнать что у вас не так: Выясните сколько строк возвращает запрос к sql серверу echo "Кол-во строк=".mysqli_num_rows($DBResult); Выводите построчно массивы c строками из запроса print_r($row); echo "<br/>\n"; "<br/>\n" - это печатам для перевода на новую строку в браузере или консоли, чтоб не было каши. Ну и так далее... Любая непонятная функция, становится понятной вот так: в браузере, в адресной строке печатаем php mysqli_real_escape_string, и увидите хорошее описание с примерами на родном для вас языке
  22. Наткнулся тут на изящную штуку для приложения с PUSH уведомлениями на Android и Ios. Один объект, все сам делает. Внедрил в одно боевое приложение с 100+ тысячами установок, полет нормальный. Описание тут https://delphiworlds.com/2017/04/firebase-cloud-messaging-android-ios/ Исходный код с примером на гитхабе https://github.com/DelphiWorlds/PushClient Использование максимально простое: uses DW.PushClient; .... private FPushClient: TPushClient; procedure PushClientChangeHandler(Sender: TObject; AChange: TPushService.TChanges); procedure PushClientReceiveNotificationHandler(Sender: TObject; const ANotification: TPushServiceNotification); .... procedure TFormMain.InitPushService; begin FPushClient := TPushClient.Create; FPushClient.GCMAppID := ConstGCMAppID; FPushClient.ServerKey := ''; FPushClient.BundleID := ''; FPushClient.UseSandbox := Debug; // Change this to False for production use! FPushClient.OnChange := PushClientChangeHandler; FPushClient.OnReceiveNotification := PushClientReceiveNotificationHandler; try FPushClient.Active := True; except SendError('FPushClient.Active Exception'); end; end; procedure TFormMain.PushClientChangeHandler(Sender: TObject; AChange: TPushService.TChanges); begin if TPushService.TChange.DeviceToken in AChange then begin HDevicePushParams.DeviceID:=FPushClient.DeviceID; HDevicePushParams.DeviceToken:=FPushClient.DeviceToken; GetHTTP(CommandRegisterFCM); // Memo1.Lines.Add('DeviceID = ' + FPushClient.DeviceID); // Memo1.Lines.Add('DeviceToken = ' + FPushClient.DeviceToken); end; end; procedure TFormMain.PushClientReceiveNotificationHandler(Sender: TObject; const ANotification: TPushServiceNotification); begin // ShowMessage(ANotification.DataObject.ToString... end; Правда руки не дошли разобраться для чего ему FPushClient.ServerKey := ''; FPushClient.BundleID := ''; Но и без этого работает.
  23. Какая версия php у вас на сервере? И судя по вашему SQL запросу (WHERE mail_index = $zapros), вы ищете данные по почтовому индексу, откуда тогда "id=г. Бишкек, ул. Токтогула, д. 191, кв. 5, под. 1". Волшебство может и случается, но не в программировании. SQL серверу вы должны дать четкие критерии поиска. Вы точно понимаете что хранится в таблице internetshop_users и как оттуда получить данные?
  24. О, это сложная и трудноуловимая ошибка ;-) Вы на Дельфи как условия пишете? Наверное вот так: if then else? А тут тоже язык программирования, и все конструкции одинаковы. Измените esle на else, и все заработает. Говорил же что в блокноте быстро накидал, опечатка...
  25. Если я не ошибаюсь, то ContentType применимо только к контенту получаемому с сервера. То вы указываете что ожидаете с сервера. Можете вообще ничего не отправлять ни в ContentType, ни в Accept. Все равно будет работать. Достаточно на стороне сервера указывать тип отдаваемого контента и обязательно кодировку (header('Content-Type: application/json; charset=utf-8')). В POST вы отправляете просто текст, и уже как вы интерпретируете на его на сервере ваше личное дело.
×
×
  • Создать...