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

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

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

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

  • Посещение

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

    100

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

  1. Может вам не писать тогда свой мессенджер а использовать что то готовое? Я в свей конторе использую http://www.commfort.com/ru/
  2. Посмотрите файлы на устройстве по пути /sys/class/tty/ , по идее должен быть файл с вашим tty устройством (com-портом). Работать с ним так же как и на linux системах - можно писать в файл и читать из него. Или погуглите фразу "android com port" - информации очень много, правда в основном для C, придется переводить на Delphi
  3. Как уже выше сказали нужно установить Билд конфигурацию - Release, и конфигурацию платформы - Application Store. Assertions не влияет, его можно оставить в любом состоянии, хотя среда по умолчанию его включает для релизной конфигурации: Assertions - Enables or disables the generation of code for assertions in a Delphi source file. The option is enabled (equivalent to {$C+}) by default. Since assertions are not usually used at run time in shipping versions of a product, compiler directives that disable the generation of code for assertions are provided. Deselect this option to disable assertions. Ошибка возникает когда в конфигурации платформы выставить "Development". На картинке выделено жирным
  4. В GetHTTP отправляю токен и id на свой сервер procedure TFormMain.GetHTTP(ACommand : String; AIndex : Integer; AImageURL : String); Var FHTTPRec : THTTPRec; AFileName, APath : String; begin .... FHTTPRec.Query:=APIURL+'?cmd='+ACommand+'&region='+Setting.RegionCode+ '&DeviceID='+HDevicePushParams.DeviceID+'&DeviceToken='+HDevicePushParams.DeviceToken; ....... FQueueRequest.PushItem(FHTTPRec); end;
  5. Вот мой код из работающего проекта, может поможет разобраться interface uses System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants, FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, System.Generics.Collections, System.JSON, FMX.TextLayout, System.IOUtils, FMX.Surfaces, System.Math, System.Net.URLClient, // SyncObjs, {$IFDEF ANDROID} FMX.Platform.Android, System.PushNotification, uVedroProcess, FMX.VirtualKeyboard, FMX.Platform, androidapi.JNI.GraphicsContentViewText, Androidapi.JNI.JavaTypes, Androidapi.JNI.Net, Androidapi.Helpers, {$ENDIF ANDROID} UnitGetHttpThread, UnitSettingPage, FMX.Controls.Presentation, FMX.StdCtrls, FMX.Advertising, FMX.Objects, UnitTypesAndFunction, FMX.Notification, FMX.Layouts, FMX.TabControl, FMX.ListView.Types, FMX.ListView, FGX.ApplicationEvents, FMX.Ani, FMX.ExtCtrls, FMX.ListBox, FMX.MultiView, FMX.Edit; ..... implementation {$IFDEF ANDROID} uses FMX.PushNotification.Android; Var APushService : TPushService; AServiceConnection : TPushServiceConnection; {$ENDIF ANDROID} {$R *.fmx} procedure TFormMain.FormCreate(Sender: TObject); begin ........ PushServiceInit; ........ end; procedure TFormMain.PushServiceInit; begin // if Debug then // Exit; try APushService:=TPushServiceManager.Instance.GetServiceByName(TPushService.TServiceNames.GCM); APushService.AppProps[TPushService.TAppPropNames.GCMAppID]:='568*********'; 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]; finally NotificationCenter:=TNotificationCenter.Create(Self); NotificationCenter.OnReceiveLocalNotification:=NotificationCenterOnReceiveLocalNotification; end; end; procedure TFormMain.ServiceConnectionOnChange(Sender: TObject; AChange: TPushService.TChanges); begin FAppStage:='ServiceConnectionOnChange start'; if AChange=[TPushService.TChange.DeviceToken] Then GetHTTP(CommandActions, -1, ''); FAppStage:='ServiceConnectionOnChange stop'; end; procedure TFormMain.ServiceConnectionOnReceiveNotification(Sender: TObject; const ANotification: TPushServiceNotification); Var JSONValue : TJSONValue; begin if ANotification.Json.TryGetValue('message',JSONValue) Then if Not JSONValue.Value.IsEmpty then begin // GetHTTP(CommandActions, -1, ''); // Memo.Lines.Add(JSONValue.Value); // ShowMessage(JSONValue.Value); end end; procedure TFormMain.NotificationCenterOnReceiveLocalNotification(Sender: TObject; ANotification: TNotification); begin // ShowMessage(ANotification.AlertBody); end; Еще забыл объявление: type TFormMain = class(TForm) ......... private { Private declarations } ...... HDevicePushParams : TDevicePushParams; .......
  6. Заметил странность - приложение запущено и видно на экране, телефон самостоятельно блокируется по таймауту, через 5-10-15 минут разблокирую телефон, вижу на экране приложение. Но приложение заморожено наглухо - контролы не реагируют, списки не прокручиваются, кнопка Назад не работает. Тоже самое приложение собранное с помощью Delphi Berlin нормально ведет себя после разблокировки, что то в Токио намудрили с UI thread. Попробовать можно на этом приложении https://play.google.com/store/apps/details?id=ru.flintnet.SuprnovaStat. 100% воспроизводится на трех телефонах, особенно хорошо на открытом TListView (можете зайти в Setting-SettingPools) P.S. Заодно можете поставить пятерку приложению. Хотя с такими глюками я бы сам не поставил.
  7. Ссылка это поиск в гугле интересующей вас информации. Думать о жутких хакерах и взломе вашего приложения можно начинать при количестве скачиваний вашего приложения от миллиона и выше. Или при стоимости приложения в несколько тысяч рублей. В противном случае гипотетических хакеров можно не принимать во внимание.
  8. Хм. Можно и так это рассматривать. Но лучше сначала изучить теоретическую часть покупок в приложении и понять что именно и для чего вы делаете. Копипастить код не поможет. Подробности тут https://www.google.ru/webhp?sourceid=chrome-instant&ion=1&espv=2&ie=UTF-8#q=покупки+в+приложениях+андроид&*
  9. Да, работал. И кстати соответствующий раздел этого форума содержит всю необходимую вам информацию.
  10. Тоже не хватает такой функции, давно смирился... Сейчас модно использовать гей-дизайнерский подход - рабочая область не должна превышать по размерам пачку сигарет. Прошу прощения за резкие высказывания - бросаю курить и не люблю дизайнеров ;-)
  11. Вот мой юнит для работы с покупками в приложении: unit UnitInAppPurchase; interface uses // UnitGetDeviceInfo, FMX.InAppPurchase, System.Classes, System.SysUtils, System.Hash; //const // HashMixer = 'p345mcq34mq'; type TBillingEventPurchased = procedure(ASecretKey : String) of object; TBillingEventNotPurchased = procedure of object; TBillingLog = procedure(AMessage : String) of object; TBilling = class private InAppPurchase: TInAppPurchase; FBillingEventPurchased : TBillingEventPurchased; FBillingEventNotPurchased : TBillingEventNotPurchased; FBillingLog : TBillingLog; FNoAdsID : String; FSecretKey : String; FApplicationLicenseKey : String; procedure InAppPurchaseSetupComplete(Sender: TObject); procedure InAppPurchaseProductsRequestResponse(Sender: TObject; const Products: TIAPProductList; const InvalidProductIDs: TStrings); procedure InAppPurchaseError(Sender: TObject; FailureKind: TFailureKind; const ErrorMessage: string); procedure InAppPurchasePurchaseCompleted(Sender: TObject; const ProductID: string; NewTransaction: Boolean); procedure ConsumeComplete(Sender: TObject; const ProductID: string); procedure ConsumeFailed(Sender: TObject; const ProductID, ErrorMessage: string); function GetSecretKey : String; function CheckSecretKey : Boolean; procedure LogMy(AMessage : String); public // Constructor Create(AApplicationLicenseKey, ANoAdsID, ASecretKey : String); constructor Create(AApplicationLicenseKey, ANoAdsID : String); destructor Destroy; procedure CheckPurchase; procedure Purchase; // published property OnPurchased : TBillingEventPurchased read FBillingEventPurchased write FBillingEventPurchased; property OnNotPurchased : TBillingEventNotPurchased read FBillingEventNotPurchased write FBillingEventNotPurchased; property OnPurchasedError : TBillingEventNotPurchased read FBillingEventNotPurchased write FBillingEventNotPurchased; property OnLog : TBillingLog read FBillingLog write FBillingLog; end; implementation //Constructor TBilling.Create(AApplicationLicenseKey, ANoAdsID, ASecretKey : String); Constructor TBilling.Create(AApplicationLicenseKey, ANoAdsID : String); begin FNoAdsID:=ANoAdsID; FApplicationLicenseKey:=AApplicationLicenseKey; // FSecretKey:=ASecretKey; InAppPurchase:=TInAppPurchase.Create(Nil); InAppPurchase.ApplicationLicenseKey:=FApplicationLicenseKey; InAppPurchase.ProductIDs.Add(FNoAdsID); InAppPurchase.OnSetupComplete := InAppPurchaseSetupComplete; InAppPurchase.OnProductsRequestResponse := InAppPurchaseProductsRequestResponse; InAppPurchase.OnError := InAppPurchaseError; InAppPurchase.OnPurchaseCompleted := InAppPurchasePurchaseCompleted; InAppPurchase.OnConsumeCompleted := ConsumeComplete; InAppPurchase.OnConsumeFailed := ConsumeFailed; end; Destructor TBilling.Destroy; begin if Assigned(InAppPurchase) then FreeAndNil(InAppPurchase); inherited; end; procedure TBilling.Purchase; begin try InAppPurchase.PurchaseProduct(FNoAdsID); except LogMy('PurchaseProduct except'); end; end; procedure TBilling.CheckPurchase; begin if CheckSecretKey Then begin LogMy('CheckSecretKey True - Disable Ads'); FSecretKey:=GetSecretKey; if Assigned(OnPurchased) then OnPurchased(FSecretKey); Exit; end; LogMy('CheckSecretKey False - Check InAppPurchase status'); InAppPurchase.SetupInAppPurchase; end; function TBilling.GetSecretKey : String; Var ADeviceIMEI : String; begin // Это был костыль для хранения флага о покупке локально, не оправдал себя и изъят из обращения // ADeviceIMEI:=GetDeviceIMEI; // Result:=System.Hash.THashSHA1.GetHashString(HashMixer+ADeviceIMEI+FNoAdsID); end; function TBilling.CheckSecretKey : Boolean; begin Result:=False; // Result:=FSecretKey.Equals(GetSecretKey); end; procedure TBilling.InAppPurchaseSetupComplete(Sender: TObject); begin LogMy('InAppPurchaseSetupComplete'); try LogMy('InAppPurchase.QueryProducts'); InAppPurchase.QueryProducts; except on E:Exception do LogMy('QueryProducts Exception: '+e.Message); end; end; procedure TBilling.InAppPurchaseProductsRequestResponse(Sender: TObject; const Products: TIAPProductList; const InvalidProductIDs: TStrings); var Product: TProduct; begin LogMy('TMainForm.InAppPurchaseProductsRequestResponse'); LogMy('Start search '+FNoAdsId); LogMy('Products.Count='+Products.Count.ToString); for Product in Products do begin LogMy('Start search '+FNoAdsId); if Product.ProductID = FNoAdsId then begin LogMy('Founded '+FNoAdsId); if InAppPurchase.IsProductPurchased(FNoAdsId) then begin // КУПЛЕНО!!!! LogMy(FNoAdsID+' Yes ProductPurchased'); FSecretKey:=GetSecretKey; if Assigned(OnPurchased) then OnPurchased(FSecretKey); end Else begin LogMy(FNoAdsID+' Not ProductPurchased'); if Assigned(OnNotPurchased) then OnNotPurchased; end; Exit; end; end; LogMy('Product not found - OnNotPurchased'); if Assigned(OnNotPurchased) then OnNotPurchased; LogMy('TMainForm.InAppPurchaseProductsRequestResponse END'); end; procedure TBilling.InAppPurchaseError(Sender: TObject; FailureKind: TFailureKind; const ErrorMessage: string); Var S: String; begin if FailureKind = TFailureKind.ProductsRequest Then S:='ProductsRequest'; if FailureKind = TFailureKind.Purchase Then S:='Purchase'; if Assigned(OnPurchasedError) then OnPurchasedError; LogMy('Purchasing error ('+S+'):'+ErrorMessage); end; procedure TBilling.InAppPurchasePurchaseCompleted(Sender: TObject; const ProductID: string; NewTransaction: Boolean); begin LogMy('TMainForm.InAppPurchasePurchaseCompleted'); if ProductID = FNoAdsID then begin LogMy('HideAndDestroyAds'); FSecretKey:=GetSecretKey; if Assigned(OnPurchased) then OnPurchased(FSecretKey); end; end; procedure TBilling.ConsumeComplete(Sender: TObject; const ProductID: string); begin LogMy('Consume Complete: ' + ProductID); end; procedure TBilling.ConsumeFailed(Sender: TObject; const ProductID, ErrorMessage: string); begin LogMy('Consume Failed: ' + ProductID); end; procedure TBilling.LogMy(AMessage : String); begin if Assigned(OnLog) then OnLog(AMessage); end; end. Использовать вот так: const NoAdsID = 'mysuperapp_remove_ad'; //название товара, тоже что и консоли разработчика ... private Billing : TBilling; procedure BillingEventPurchased(ASecretKey : String); procedure BillingEventNotPurchased; procedure BillingEventPurchasedError; procedure BillingLog(AMessage : String); procedure DisablePurchaseUI; procedure EnablePurchaseUI; ... FormCreate start Var AppLicenseKey : String; ... AppLicenseKey:='MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxim8ZGAIhK/FPhpXT0r6MXHYxYi1qcMfIiKOkiBDHcRYgRLK7'; AppLicenseKey:=AppLicenseKey+'********************************************************************************'; AppLicenseKey:=AppLicenseKey+'******************************************************************************'; AppLicenseKey:=AppLicenseKey+'*******************************************************************************'; AppLicenseKey:=AppLicenseKey+'Mgv7JP8A+qcDV3lm4M9OKBgxBRLaejxHd1iH3tsMR8PLkKUUf3yrMW8QIDAQAB'; Billing:=TBilling.Create(AppLicenseKey, NoAdsID); Billing.OnPurchased:=BillingEventPurchased; Billing.OnNotPurchased:=BillingEventNotPurchased; Billing.OnPurchasedError:=BillingEventPurchasedError; Billing.OnLog:=BillingLog; Billing.CheckPurchase; FormCreate stop ... procedure TFormMain.BillingEventPurchased(ASecretKey : String); begin // LogMy('CheckSecretKey True - Disable Ads'); Setting.Flags.AdsShowFlag:=False; DisablePurchaseUI; // удаляет кнопки и прочую фигню предлагающую купить товар (товар в данном случае - Удаление рекламы) HideAndDestroyAds; // удаление рекламы из приложения, так как товар куплен // Setting.SecretKey:=ASecretKey; // SaveFormState; end; procedure TFormMain.BillingEventNotPurchased; begin Setting.Flags.AdsShowFlag:=True; EnablePurchaseUI; ShowAds; end; procedure TFormMain.BillingEventPurchasedError; begin Setting.Flags.AdsShowFlag:=True; // EnablePurchaseUI; ShowAds; end; procedure TFormMain.BillingLog(AMessage : String); begin // Memo.Lines.Insert(0,AMessage); end; procedure TFormMain.DisablePurchaseUI; begin ButtonRemoveAds.Visible:=False; LayoutRemoveAds.Visible:=False; end; procedure TFormMain.EnablePurchaseUI; begin LayoutRemoveAds.Visible:=True; ButtonRemoveAds.Visible:=True; end;
  12. А можно мне версию с показом фотографий котиков? ;-)
  13. Можно поступить проще - заливать в полуручном режиме procedure ShareFile(aFileName, aComment : String); {$IFDEF ANDROID} var Intent : JIntent; uri : Jnet_Uri; AttachmentFile: JFile; S : String; {$ENDIF ANDROID} begin {$IFDEF ANDROID} Intent := TJIntent.Create; Intent.setAction(TJIntent.JavaClass.ACTION_SEND); Intent.setFlags(TJIntent.JavaClass.FLAG_ACTIVITY_NEW_TASK); S:=TPath.GetFileName(aFileName); 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')); // Intent.setDataAndType(StrToJURI('file:' + TPath.Combine(TPath.GetSharedDownloadsPath, 'picture.png')), StringToJString ('image/png')); SharedActivity.startActivity(Intent); {$ENDIF ANDROID} end; Пользователю выведется диалог отправки файла, он должен будет выбрать DropBox... Конечно это решение для разовой отдачи, если нужно регулярная отсылка в авторежиме, то оно не подойдет.
  14. У автора те же ошибки что и у меня, причем на этом он и завершил свое повествование, типа "ну не получилось..."
  15. Не выходит каменная чаша... Вроде все сделал правильно, но при загрузке пакета получаю ошибки:
  16. Видимо никак. Проще сделать свой MessageBox - layout на весь экран, на него все остальное. Я уперся рогом и минут сорок пытался закрыть, вот что уже попробовал (но не сработало): procedure TForm1.Timer1Timer(Sender: TObject); Var APointF : TPointF; Key: Word; KeyChar: System.WideChar; MessageBase : TMessageBase; begin Memo1.Lines.Add('Срабатывает таймер'); APointF.X:=100; APointF.Y:=100; Key:=vkHardwareBack; KeyChar:=#0; // Self.BringToFront; // MessageBase:=TMessageBase.Create; // Self.VirtualKeyboardChangeHandler(Self, MessageBase); // SetFocused(); // Self.KeyDown(Key, KeyChar, []); // Self.Focused.SetFocus; // Self.Tap(APointF); // Self.DoTap(APointF); // Self. Action. Tap(APointF); Timer1.Enabled:=False;
  17. Элементарно - TListBoxItem.Text:='Это включает такую то фичу';
  18. Кидаете на форму TListBox, правой кнопкой по нему и через контекстное меню создаете TListBoxItem. В TListBoxItem кидаете TLabel с выравниванием по левому краю, пишите текст "Это включает такую то фичу". В тот же TListBoxItem кидаете нужный контрол, к примеру TSwitch с выравниванием по правому краю и привязываете к нему нужный код. Все, повторяете необходимое количество раз. Если нужно много подобного - проделываете тоже самое в процессе выполнения приложения программно.
  19. В Tokyo данный косяк решили сохранить, видимо он им дорог как память :-) Вот кусок из System.Net.HttpClient.Win.pas // Send data if DataLength > 0 then begin SetLength(Buffer, BUFFERSIZE); while LRequest.FSourceStream.Position < LRequest.FSourceStream.Size do begin ToRead := LRequest.FSourceStream.Size - LRequest.FSourceStream.Position; if ToRead > BUFFERSIZE then ToRead := BUFFERSIZE; LRequest.FSourceStream.ReadBuffer(Buffer, ToRead); // Write data to the server. if not WinHttpWriteData(LRequest.FWRequest, Buffer[0], ToRead, @BytesWritten) then raise ENetHTTPClientException.CreateResFmt(@SNetHttpClientSendError, [GetLastError, SysErrorMessage(GetLastError, FWinHttpHandle)]); if BytesWritten < ToRead then LRequest.FSourceStream.Position := LRequest.FSourceStream.Position - (ToRead - BytesWritten); end; end;
  20. Я для таких целей использую TListBox. Проще и удобнее. Плюс некоторые строки по мере надобности можно скрывать/показывать.
  21. Эта плюшка уже есть в TEdit, называется TEdit.TextPrompt
  22. Пока нашел только одно решение. Только для случая с TListView, и только с одной картинкой на ListViewItem. Да, и только для Tokyo (добавили TListViewItem.TagObject) AListItem:=ListView.Items.Add; AListItem.TagObject:=TMemoryStream.Create; FAsyncResponse := FHTTPClient.BeginGet(DoEndDownload, URL, AListItem.TagObject as TMemoryStream); Т.е. MemoryStream, в который производится скачивание, мы создали в AListItem.TagObject, по окончании загрузки будем знать в какую картинку какого итема грузить .
×
×
  • Создать...