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

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

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

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

  • Посещение

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

    100

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

  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. letsencrypt.org предоставляет сертификат для сайтов и список способов их установки/обновления. Рекомендуемый это https://certbot.eff.org/ - выбираем софт, выбираем операционку и вперед. Инструкции очень подробные. Да, еще зависит от того какой уровень доступа к вашему серверу, есть доступ к шеллу или нет.На https://letsencrypt.org/getting-started/ все пошагово расписано. Будут затыки, пишите в телеграм - чем смогу помогу
  11. Я получал, получаю и буду получать ;-) Все бесплатно, срок 3 месяца, но продление полностью автоматизировано (по крону запускаешь скрипт и она сам продляет). Отличная система, рекомендую.
  12. enatechno выше привел ссылки на статьи где все расписано по полочкам.
  13. Не действительны сертификаты SSL Certificates (для web-серверов). У них все сертификаты всегда были бесплатными (поэтому их американские монстры и прижали), платная только проверка пользователя - т.е. один раз проходишь валидацию нужного тебе класса и целый год выпускаешь сертификаты бесплатно.
  14. apptethering довольно убогий (его реализация в дельфи) - написали по быстрому модную технологию и забросили. Если не ошибаюсь, за все время существования компонента ни разу он не был исправлен или доделан. Для вашего случая проще и быстрее использовать Indy (UDP сервер и клиент) - для одновременного получения клиентами сообщения отсылаете его сервером в multicast режиме на какой нибудь порт, клиенты получат его одновременно. В apptethering не знают про multicast, по крайней мере в исходниках не нашел и потоки используются только временами и не предсказуемо.
  15. Я обычно получаю сертификат в https://www.startcomca.com - самый не дорогой сервис. Сначала нужно получить Class 2 Personal Identity Validation за US$59.90, потом можно будет генерировать неограниченное количество подписей. Сервис хорош тем что предоставляет архив с подписями, инструкциями и инструментарием (остальные сервисы дадут текстовый файлик с подписью в непредсказуемом контейнере - и разбирайся сам...). Пинаю потихоньку https://kontur.ru/ca , дабы начали на территории России выдавать сертификаты Code Signing, но пока только за бугром это можно сделать.
  16. О, спасибо! Значит ListItemImage.OwnsBitmap управляет типом ссылки на Bitmap - False - слабая ссылка, True нормальная ссылка. Вот почему в документации это не указать?
  17. Как в FMX Memo задать размер таба (символа с кодом #9)? По умолчанию он гигантский. Все способы из гугля оперируют или VCL Memo или win api. Нужно мультиплатформенное решение.
  18. У него на гитхабе внизу есть пометка но что за KastriFree project я не успел посмотреть, может там все есть. Под андроидом работает отлично. Давно сам хотел все в отдельном модуле оформить, но тут удачно наткнулся...
  19. 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, и увидите хорошее описание с примерами на родном для вас языке
  20. Наткнулся тут на изящную штуку для приложения с 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 := ''; Но и без этого работает.
  21. Какая версия php у вас на сервере? И судя по вашему SQL запросу (WHERE mail_index = $zapros), вы ищете данные по почтовому индексу, откуда тогда "id=г. Бишкек, ул. Токтогула, д. 191, кв. 5, под. 1". Волшебство может и случается, но не в программировании. SQL серверу вы должны дать четкие критерии поиска. Вы точно понимаете что хранится в таблице internetshop_users и как оттуда получить данные?
  22. О, это сложная и трудноуловимая ошибка ;-) Вы на Дельфи как условия пишете? Наверное вот так: if then else? А тут тоже язык программирования, и все конструкции одинаковы. Измените esle на else, и все заработает. Говорил же что в блокноте быстро накидал, опечатка...
  23. Если я не ошибаюсь, то ContentType применимо только к контенту получаемому с сервера. То вы указываете что ожидаете с сервера. Можете вообще ничего не отправлять ни в ContentType, ни в Accept. Все равно будет работать. Достаточно на стороне сервера указывать тип отдаваемого контента и обязательно кодировку (header('Content-Type: application/json; charset=utf-8')). В POST вы отправляете просто текст, и уже как вы интерпретируете на его на сервере ваше личное дело.
×
×
  • Создать...