-
Постов
2 517 -
Зарегистрирован
-
Посещение
-
Победитель дней
264
Активность репутации
-
Равиль Зарипов (ZuBy) отреагировална Rusland в "Общение" сервиса и приложения через intent
Для ищущих ответа:
Есть стандартное demo Object Pascal\Mobile Snippets\AndroidIntents\AndroidIntentsGroup.groupproj, в котором показано как из одного приложения передавать данные другому. С помощью этого примера удалось передавать данные из сервиса в основное приложение.
В юните основного приложения пишем:
uses FMX.Platform, FMX.Platform.Android, Androidapi.JNI.JavaTypes, Androidapi.JNI.Net, Androidapi.JNI.Os, Androidapi.Helpers, System.Messaging, Androidapi.JNI.GraphicsContentViewText; private { Private declarations } function HandleAppEvent(AAppEvent: TApplicationEvent; AContext: TObject): Boolean; procedure HandleActivityMessage(const Sender: TObject; const M: TMessage); function HandleIntentAction(const Data: JIntent): Boolean; procedure TForm1.FormCreate(Sender: TObject); var AppEventService: IFMXApplicationEventService; begin ... if TPlatformServices.Current.SupportsPlatformService(IFMXApplicationEventService, AppEventService) then AppEventService.SetApplicationEventHandler(HandleAppEvent); // Register the type of intent action that we want to be able to receive. // Note: A corresponding <action> tag must also exist in the <intent-filter> section of AndroidManifest.template.xml. MainActivity.registerIntentAction(TJIntent.JavaClass.ACTION_VIEW); TMessageManager.DefaultManager.SubscribeToMessage(TMessageReceivedNotification, HandleActivityMessage); end; procedure TForm1.HandleActivityMessage(const Sender: TObject; const M: TMessage); begin if M is TMessageReceivedNotification then HandleIntentAction(TMessageReceivedNotification(M).Value); end; function TForm1.HandleAppEvent(AAppEvent: TApplicationEvent; AContext: TObject): Boolean; var StartupIntent: JIntent; begin Result := False; if AAppEvent = TApplicationEvent.BecameActive then begin StartupIntent := MainActivity.getIntent; if StartupIntent <> nil then HandleIntentAction(StartupIntent); end; end; function TForm1.HandleIntentAction(const Data: JIntent): Boolean; var Extras: JBundle; begin Result := False; if Data <> nil then begin Memo1.ClearContent; // записываем в Memo пришедшее сообщение Extras := Data.getExtras; if Extras <> nil then Memo1.Text := JStringToString(Extras.getString(TJIntent.JavaClass.EXTRA_TEXT)); Invalidate; end; end; в AndroidManifest.template.xml добавляем
<action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> <data android:mimeType="text/pas" /> Отправка сообщения из сервиса делается так:
SendTextViaIntent('Hello from service'); procedure TAndroidServiceDM.SendTextViaIntent(const AText: string); var Intent: JIntent; begin Intent := TJIntent.Create; Intent.setType(StringToJString('text/pas')); Intent.setAction(TJIntent.JavaClass.ACTION_VIEW); Intent.setFlags(TJIntent.JavaClass.FLAG_ACTIVITY_NEW_TASK); // добавил такой флаг, без него сервис затыкался Intent.putExtra(TJIntent.JavaClass.EXTRA_TEXT, StringToJString(AText)); if TJContextWrapper.Wrap(System.JavaContext).getPackageManager.queryIntentActivities(Intent, TJPackageManager.JavaClass.MATCH_DEFAULT_ONLY).size > 0 then TJContextWrapper.Wrap(System.JavaContext).startActivity(Intent); // заменил MainActivity на TJContextWrapper.Wrap(System.JavaContext), т.к. это сервис end; Работает исправно, хоть 100%-ую правильность кода не гарантирую Но как передать сообщение из основной программы обратно в сервис я пока не знаю. Также делать хендл внутри сервиса?
Попытался просто добавить FMX.Platform, в результате получаю ошибку в FMX.Platform.Android вываливается ошибка об использовании Activity внутри сервиса. -
Равиль Зарипов (ZuBy) отреагировална Brovin Yaroslav в [Android] Как изменить цвет системного статус бара и разместить контролы под ним?
Поскольку тема вызывает не поддельный интерес у пользователей. Я расскажу, как это делал я для одной демо программы, которую я готовил для выступления в ИТМО. Сразу приложу скриншот, как это будет выглядеть:
Сразу скажу, что это решение временное и имеет ряд определенных нюансов, которые появятся после его использования. О том, как исправить эти нюансы указано в самом конце.
Теперь к делу. Андроид позволяет сделать статус бар прозрачным с наложением белого цвета с альфа каналом. Это значит, если мы разместим под статус баром зеленый цвет, то статус бар станет соответствующего темно зеленого цвета. Этим и воспользуемся. Основная идея такая:
Говорим Андроиду, что хотим прозрачный статус бар. Указываем андроиду, что хотим размещать форму под статус баром. Размещаем под статус баром TRectangle нужного цвета, в тон TToolBar (если используете) Теперь по шагам:
1. Говорим Андроиду, что хотим прозрачный статус бар. Указываем андроиду, что хотим размещать форму под статус баром.
Создаем файл style.xml со стилем для нашего приложения.
<resources xmlns:android="http://schemas.android.com/apk/res/android"> <style name="AppTheme" parent="@android:style/Theme.Holo.Light"> <item name="android:windowTranslucentStatus">true</item> <item name="android:windowTranslucentNavigation">true</item> <item name="android:windowBackground">@drawable/splash_image_def</item> <item name="android:windowNoTitle">true</item> </style> </resources> В стиле указываем, что мы хотим использовать прозрачный статус бар.
Открываем Менеджер развертывания Menu->Project->Deployment Manager и добавляем наш файл стиля в проект только для андроид конфигураций:
Remote Path: "res\values\" Remote Name: "styles.xml" Теперь при запуске программы, андроид будет считать, что:
Приложение будет развернуто на весь экран Статус бар будет прозрачного цвета. 3. Размещаем под статус баром TRectangle нужного цвета, в том TToolBar (если используете)
Я разместил вверху формы TRectangle, который залил требуемым цветом, в тон тул бару:
Высота статус бара у андроида равна 24.
Если вы делаете кроссплатформенный проект и для ios тоже, то по умолчанию скрываем этот прямоугольник и добавляем код по его отображению в конструктор формы только на андроиде
constructor TFormMain.Create(AOwner: TComponent); begin inherited Create(AOwner); {$IFDEF ANDROID} SystemStatusBarBackground.Visible := True; {$ENDIF} end; В принципе все готово.
Побочные эффекты
По скольку это решение сделано сбоку, то пара моментов, которые придется в вашей программе следить:
Нативные контролы распологаются по старому, полагая, что форма располагается под статус баром, а не под формой. Поэтому для нативных контролов таких, как TMapView, нужно корректировать позицию или отступы. {$IFDEF ANDROID} MapView.Margins.Top := -SystemStatusBarBackground.Height; {$ENDIF} Формы располагается так же и под нижними программными кнопками: Назад, домой и меню. Поэтому нужно так же иметь в виду, что расположенные снизу контролы, не будут кликабельны. Так как перекрываются нижней панелью с кнопками. Решение - это разместить TLayout под нижней панелью, чтобы сдвинуть ваши контролы к верху. -
Равиль Зарипов (ZuBy) отреагировална FeLDMARShaL в Режим звонка
В обычном режиме приложение выглядит хорошо и правильно. Однако если кто топозвонить, и пользователь свернет звонок и вернется в приложение, то можно наблдать следующий баг.
-
Равиль Зарипов (ZuBy) отреагировална zairkz в Режим звонка
Такое же поведение наблюдается если включить на Iphone режим модема, и к Iphone подключить хотя бы одно устройство. Но пока понятия не имею что с этим сделать.
-
Равиль Зарипов (ZuBy) получил реакцию от Axbor в [TidHTTP] Почему IdHttp1.Get может выдавать 404 ошибку, файл не найден?
function idHttpGet(const aURL: string): string; // uses System.Net.HttpClient, System.Net.HttpClientComponent, System.Net.URLClient; var Resp: TStringStream; Return: IHTTPResponse; begin Result := ''; with TNetHTTPClient.Create(nil) do begin Resp := TStringStream.Create('', TEncoding.ANSI); Return := Get( { TURI.URLEncode } (aURL), Resp); Result := Resp.DataString; Resp.Free; Free; end; end; procedure TForm1.Button1Click(Sender: TObject); begin ShowMessage(idHttpGet('http://airnav.tj/ru/online/utdd')); end; Держи
-
Равиль Зарипов (ZuBy) получил реакцию от Vitaldj в [TidHTTP] Почему IdHttp1.Get может выдавать 404 ошибку, файл не найден?
function idHttpGet(const aURL: string): string; // uses System.Net.HttpClient, System.Net.HttpClientComponent, System.Net.URLClient; var Resp: TStringStream; Return: IHTTPResponse; begin Result := ''; with TNetHTTPClient.Create(nil) do begin Resp := TStringStream.Create('', TEncoding.ANSI); Return := Get( { TURI.URLEncode } (aURL), Resp); Result := Resp.DataString; Resp.Free; Free; end; end; procedure TForm1.Button1Click(Sender: TObject); begin ShowMessage(idHttpGet('http://airnav.tj/ru/online/utdd')); end; Держи
-
Равиль Зарипов (ZuBy) получил реакцию от R.is в Как реализовать это?
Да пожалуйста, пользуйтесь.
У Itema же есть Bitmap. Если нужно через инет, то нужно через хелпер тут не раз выкладывали
Есть тема от меня в разделе TListView про динамическую загрузку картинок, посмотрите там.
-
Равиль Зарипов (ZuBy) получил реакцию от Tom1984 в Динамическая подгрузка картинок в ListView
Привет Всем!
Как принято в современных приложениях, догружать контент(обычно это картинки) при скролинге.
я взял картинки пользователей этого форума
Seattle LVdynamicLoadBitmap.zip
Berlin LVdynamicLoadBitmap(Berlin).zip
-
Равиль Зарипов (ZuBy) получил реакцию от DimArt в Как реализовать это?
что-то типа этого?
demoLV.zip
-
Равиль Зарипов (ZuBy) получил реакцию от HyperZen в Запрос на закрытие приложения при нажатии кнопки Назад
Если внимательно смотреть, то не бывает диалогов с одной кнопкой Yes, всегда OK
case AResult of mrOk: Close; end; -
Равиль Зарипов (ZuBy) отреагировална Brovin Yaroslav в Как узнать поддерживаемый максимально допустимый размер изображения в TBitmap?
В FireMonkey TBitmap имеет верхнее ограничение на размеры хранимого изображения, ограниченные максимально допустимым размером текстур в текущей платформе. Узнать максимальную ширину и высоту можно так:
var MaxWidthHeight: Integer; begin MaxWidthHeight := TCanvasManager.DefaultCanvas.GetAttribute(TCanvasAttribute.MaxBitmapSize); end; -
Равиль Зарипов (ZuBy) отреагировална krapotkin в Прочитать item'ы из listView
но лучше - не хранить данные в элементах интерфейса
-
Равиль Зарипов (ZuBy) получил реакцию от zairkz в Поменять цвет статус бара Delphi [XE7] - Android
Возможно это работает также как и для IOS...
У меня получилось
Код не изменился, изменения были в форме...
Нужно задать цвет
Form1.Fill.Color := TAlphaColorRec.Red; Посередине я поставил Rectangle, чтобы цвет контента не был равен цвету форме.
и снизу стоит Rectangle с черным цветом, т.к. у меня наэкранные кнопки.
если убрать нижняя панель тоже покрасится.
И теперь вопрос, кто знает как определить высоту наэкранных кнопок и их существование?
P.S. Кривяков Виталий спасибо за модуль
-
Равиль Зарипов (ZuBy) получил реакцию от Kitty в Поменять цвет статус бара Delphi [XE7] - Android
Возможно это работает также как и для IOS...
У меня получилось
Код не изменился, изменения были в форме...
Нужно задать цвет
Form1.Fill.Color := TAlphaColorRec.Red; Посередине я поставил Rectangle, чтобы цвет контента не был равен цвету форме.
и снизу стоит Rectangle с черным цветом, т.к. у меня наэкранные кнопки.
если убрать нижняя панель тоже покрасится.
И теперь вопрос, кто знает как определить высоту наэкранных кнопок и их существование?
P.S. Кривяков Виталий спасибо за модуль
-
Равиль Зарипов (ZuBy) отреагировална Кривяков Виталий в Поменять цвет статус бара Delphi [XE7] - Android
Да, тоже столкнулся с тем, что цвет становиться белым и не меняется.
Вот версия без необходимости менять исходники.
SystemBar.zip
-
Равиль Зарипов (ZuBy) отреагировална zairkz в Поменять цвет статус бара Delphi [XE7] - Android
Может Ярослав подключится на досуге, всем надо бы такую штуку)
-
Равиль Зарипов (ZuBy) отреагировална zairkz в показать 9-patch в TstyleObject
Сохраните ваш стиль, откройте блокнотом найдите нужный вам итем стиля, добавьте отступы например:
SourceLink = < item CapInsets.Left = 8.000000000000000000 CapInsets.Top = 8.000000000000000000 CapInsets.Right = 8.000000000000000000 CapInsets.Bottom = 8.000000000000000000 SourceRect.Left = 208.000000000000000000 SourceRect.Top = 249.000000000000000000 SourceRect.Right = 248.000000000000000000 SourceRect.Bottom = 293.000000000000000000 end после чего у вас дизайнере появиться дополнительная область выделения, по ней и настраивайте область для растягивания
-
Равиль Зарипов (ZuBy) отреагировална Brovin Yaroslav в [TfgRichEdit]- компонент редактирования текста с поддержкой форматирования
Пока не знаю. Недавно оптимизировал скорость отрисовки. Теперь у меня документ занимает в ~2 раз меньше узлов дерева, чем до оптимизации. Сейчас работаю над оптимизацией плавной прокрутки на мобильных платформах.
-
Равиль Зарипов (ZuBy) отреагировална Brovin Yaroslav в показать 9-patch в TstyleObject
Там же, в коллекции линка есть и отступы, они как раз и отвечают за размеры боковых и угловых областей, которые не растягиваются.
-
Равиль Зарипов (ZuBy) отреагировална Antonyan в Можно ли у TListViewItem при добавлении его в TListView установить свойство Accessory в None?
Как вариант, можно просто скрыть его
Procedure XXX;
Var
LItem : TListViewItem;
begin
LItem := YourListView.Items.Add;
LItem.Objects.AccessoryObject.Visible:=false;
end;
-
Равиль Зарипов (ZuBy) получил реакцию от zairkz в Как правильно рисовать на канве?
спец) он один из разработчиков Firemonkey
-
Равиль Зарипов (ZuBy) отреагировална Andrey Efimov в TListViewHorz
Axbor
Всё нормально скачивается, на всякий случай сделал 30 дневное зеркало: http://rghost.ru/7KvGrv9K6
-
Равиль Зарипов (ZuBy) отреагировална Brovin Yaroslav в Как сделать вывод текста в верхнем/нижнем регистре для отображения математической степени или индекса?
Добрый день,
Пока, к сожалению, нету поддержки стиля верхнего и нижнего регистров для текста. Поэтому вместо жонглирования TText, я бы сделал свой компонент. В нем достаточно будет только определить метод Paint для отрисовки текста. Дальше просто:
TTextLayout используем для измерения размеров текста. Потом согласно расчетам, просто выводим в нужные позиции текст. Для вдохновения можно сделать по образу и подобию TText.
Расчет размеров текста:
ATextLayout.BeginUpdate; try ATextLayout.Text := Text; ATextLayout.WordWrap := False; ATextLayout.MaxSize := TSizeF.Create(1000, 1000); finally ATextLayout.EndUpdate; end; Result := ATextLayout.TextRect.Size; Вывод текста:
либо так:
AContext.Canvas.FillText(Bounds, Text, False, 1, [], TTextAlign.Leading); Либо через TTextLayout:
ATextLayout.Render; Вам остается только добавить логику по вычислению позиции верхнего или нижнего регистра относительно основного текста.
-
Равиль Зарипов (ZuBy) получил реакцию от МихаилЪ чайковЪ в TListViewHorz
Давно не хватало TListView в горизонтальной ориентации, например чтобы сделать вот такую картинку
zairkz сделал стиль с применением 9-patch png "технологии"
С помощью жестов показано как сделать "сквозной скрол"
как писал dreamix
P.S. по компоненту TListViewHorz, не успел все протестить как следует со всеми параметрами
не правильно будет отображаться Header'ы и Поиск, основной функционал сохранен
UPDATE: LVStyledhorz.7z
-
Равиль Зарипов (ZuBy) получил реакцию от Alisson R Oliveira в SuperObject vs JSON
Привет Всем!
Решил поделится впечатлениями по работе с SuperObject'ом и родным JSON'ом
тест был файла с 2000+ объектами в JSON файле
структура файла была такая
{ "status":"OK", "last_id":"711", "objects":[ { "obj_id":"1", "obj_acc_id":"1", "obj_cat_id":"24", "obj_title":"13 магистраль", "obj_descr":"ЖК представляет собой комфортный дом, состоящий из 14 блок-секций (подъездов). Расположен в перспективном развивающемся районе по 13 Магистрали с удобным выездом как на левый берег, так и в старую часть города. Вблизи Жилого комплекса распологается новая школа, парк отдыха и культуры.", "obj_address":"ул. Мамышулы - 104, д. 16\/1", "obj_address2":null, "obj_url":"3fa07dd73be072b049529c80c7d74732", "obj_planet":"1", "obj_country":"1", "obj_region":"1", "obj_city":"292", "obj_lat":"51.141", "obj_lon":"71.4835", "obj_insert_dt":null, "obj_update_dt":null, "obj_editted":"0", "obj_updated":"0", "obj_deleted":"0", "obj_showed":"1", "obj_rating":"0", "obj_pro_top":"0", "obj_pro_selected":"0", "obj_pro_unix_dt":"0", "obj_partner":"0", "obj_parent_id":"0", "obj_has_child":"0", "obj_currency":"0" }, // тут далее 2000+ объектов ] } SuperObject Время выполнения: ~01:393
JSON родной Время выполнения: ~01:690
разница не особо ощутима, тем более если будет меньше объектов
JSON родной
function JSONParse(const aJSONData: string; const aMemo: TMemo): boolean; var aJSValue: TJSONValue; aJSObject, aJSObjArr: TJSONObject; aJSArray: TJSONArray; I: integer; begin Result := false; aJSValue := TJSONObject.ParseJSONValue(aJSONData) as TJSONValue; if Assigned(aJSValue) then begin aJSObject := aJSValue as TJSONObject; aMemo.Lines.Add('status: ' + aJSObject.GetValue('status').Value); if aJSObject.GetValue('status').Value = 'OK' then begin Result := true; if Assigned(aJSObject) then begin aJSArray := aJSObject.GetValue('objects') as TJSONArray; if Assigned(aJSArray) then begin Result := true; aMemo.Lines.Add('last_id: ' + aJSObject.GetValue('last_id').Value); aMemo.Lines.Add('count: ' + aJSArray.Count.ToString); for I := 0 to aJSArray.Count - 1 do begin aJSObjArr := aJSArray.Items[I] as TJSONObject; if Assigned(aJSObjArr) then begin aMemo.Lines.Add(aJSObjArr.GetValue('obj_id').Value + ',' + aJSObjArr.GetValue('obj_acc_id').Value + ',' + aJSObjArr.GetValue('obj_cat_id').Value); aMemo.Lines.Add(aJSObjArr.GetValue('obj_title').Value); aMemo.Lines.Add(aJSObjArr.GetValue('obj_descr').Value); aMemo.Lines.Add(aJSObjArr.GetValue('obj_address').Value); aMemo.Lines.Add(aJSObjArr.GetValue('obj_url').Value); end; end; end; end; end; aJSValue.Free; end; end; SuperObject
function JSONSOParse(const aJSONData: string; const aMemo: TMemo): boolean; var xObject: ISuperObject; xCount, I: integer; sfmt: string; begin Result := false; xObject := SO(aJSONData); aMemo.Lines.Add('status: ' + xObject['status'].AsString); if xObject['status'].AsString = 'OK' then begin Result := true; xCount := xObject['objects'].AsArray.Length; aMemo.Lines.Add('count: ' + xCount.ToString); aMemo.Lines.Add('last_id: ' + xObject['last_id'].AsInteger.ToString); for I := 0 to xCount - 1 do begin aMemo.Lines.Add(xObject['objects[' + I.ToString + ']."obj_id"'].AsInteger.ToString + ',' + xObject['objects[' + I.ToString + ']."obj_acc_id"'].AsInteger.ToString + ',' + xObject['objects[' + I.ToString + ']."obj_cat_id"'].AsInteger.ToString); aMemo.Lines.Add(xObject['objects[' + I.ToString + ']."obj_title"'].AsString); aMemo.Lines.Add(xObject['objects[' + I.ToString + ']."obj_descr"'].AsString); aMemo.Lines.Add(xObject['objects[' + I.ToString + ']."obj_address"'].AsString); aMemo.Lines.Add(xObject['objects[' + I.ToString + ']."obj_url"'].AsString); end; end; end; Разница ощутима когда пишешь код, SO намного легче читать
Подробней почитать и скачать SO