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

PowerOwl

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

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

  • Посещение

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

    7

Активность репутации

  1. Like
    PowerOwl отреагировална Andrey Efimov в Android 10 и муз.плеер   
    У меня на устройстве с Андроид 11 и эмуляторе с Андроид 7.1.2 приложение не падает.

    По теме, делайте дебаг версию и ищите устройство на котором падает, запускайте monitor.bat и приложение, снимайте логи и выкидывайте их сюда. Это нужно сделать как минимум для того чтобы убедиться в ваших догадках (что происходит падение из-за сервиса). Так же попробуйте вынести в кнопку код запуска сервиса.
    Документация по Foreground service: https://developer.android.com/guide/components/foreground-services
     
     
  2. Sad
    PowerOwl отреагировална slav_z в LSP Server for Delphi   
    Оставил без присмотра IDE 10.4.2 на 2 часа... возвращаюсь, смотрю:  комп гудит... выгрузил IDE...но это осталось и уже полчаса что-то пытается делать... вот не дурак?

     
    не знаю..  временами уже хочется дать программистам (маркетологам?) embarcadero пизд*юлей..  терпения нет уже...  а по модулям в uses так и не переходит.... хоть и говорят что исправили... даже хуже стало...  похоже скоро вообще без отладки оставят... "на ощупь" программы пишу уже... как в блокноте... рассылки их дурацкие..  книги-пустышки бесплатные... вебинары ни о чем... хоть бы что-нибудь путное было... толку от их разработчиков-пенсионеров "марко канту" которые ничего не делают для сообщества... все!!! все компоненты содержат серьезные ошибки и недоработки.. ВСЕ!!!!! 10 лет фреймворку FMX!!! каждый день как на битву... с у к а...
  3. Thanks
    PowerOwl получил реакцию от Ingalime в Android 10 и муз.плеер   
    Протестировал на устройстве с Android 10(Nokia 3.1), всё прекрасно работает. Музыка работает, при сворачивании не падает, с выключенным экраном тоже.
     

  4. Thanks
    PowerOwl получил реакцию от Ingalime в Android 10 и муз.плеер   
    Я попробовал запустить на Android 6.0.1, при старте падает после показа картинки. Однако я не знаю, какой минимальный sdk level у приложения, может оно и не должно запускаться на шестёрке. В любом случае, просто отписался.
    Хотя в манифесте написано, что minSdkVersion='23', что соответствует Андроид 6
  5. Like
    PowerOwl получил реакцию от Ingalime в Использование Android DownloadManager   
    Здравствуйте! Хочу поделиться своим опытом в использовании класса android.app.DownloadManager из Android API.
    Понятно из названия, что этот класс предоставляет пользователю возможность скачивать и сохранять файлы из интернета. Конечно, можно использовать HTTPClient, но по моему мнению использование DownloadManager гораздо легче.
    Возможности, предоставляемые классом:
    1.Скачивание любого файла из интернета с последующим сохранением
    2.Вывод уведомления о процессе загрузки с настраиваемым названием и описанием
    3.Разрешение загрузки только через конкретный вид сети, через роуминг, когда девайс заряжается и т.д.
    Вот ссылки на официальную документацию по классу DownloadManager и его подклассу DownloadManager.Request: https://developer.android.com/reference/android/app/DownloadManager
    https://developer.android.com/reference/android/app/DownloadManager.Request
    Демо-проект и обёртку для класса и прикрепил внизу.
    В примере по нажатию на кнопку происходит загрузка картинки в директорию /storage/emulated/0/Pictures
    -----------------------------------------------------------------------------
    Для начала, необходимо подключить библиотеки, необходимые приложению для работы:
    uses androidapi.JNI.JavaTypes, androidapi.Helpers, androidapi.JNI.GraphicsContentViewText, android.app.DownloadManager, androidapi.JNI.Net, System.Permissions, Androidapi.JNI.Os; Теперь нужно запросить у пользователя разрешение на запись в хранилище:
    procedure TForm1.FormCreate(Sender: TObject); var WRITE_EXTERNAL_STORAGE:String; begin WRITE_EXTERNAL_STORAGE:=JStringToString(TJManifest_permission.JavaClass.WRITE_EXTERNAL_STORAGE); PermissionsService.DefaultService.RequestPermissions([WRITE_EXTERNAL_STORAGE], procedure(const APermissions: TArray<string>; const AGrantResults: TArray<TPermissionStatus>) begin if (Length(AGrantResults)=1) and (AGrantResults[0]=TPermissionStatus.Granted) then ShowMessage('Permission granted!') else begin Showmessage('Permission Denied! Manually go to "Settings-Applications-Project1-Permissions" and set Storage permission!'); Application.Terminate; end; end ) end; Если разрешение получено, то появится сообщение "Permission granted!", если нет, то программа попросит пользователя перейти в настройки и установить разрешение вручную.
    Отлично, разрешение получено, теперь можно написать и саму процедуру загрузки файла.
    procedure Download(code: string); //процедура будет получать уникальный код картинки на сайте pixabay.com var DownloadManager: JDownloadManager; //Объект класса DownloadManager для загрузки файла DownloadRequest: JDownloadManager_Request; //Объект класса DownloadManager_Request для установки настроек загрузки link: JString; //Переменная для хранения ссылки URI, URIPath: JNet_URI; //В URI будем получать ссылку на картинку, в URIPath - путь к загруженной картинке в файловой системе DownloadPermission: JObject; //Объект для получения доступа к сервису загрузки begin link := StringToJString('https://pixabay.com/get/' + code + '_1280.jpg'); //получаем ссылку на картинку URI := TJNet_URI.JavaClass.parse(link); //заносим ссылку в URI URIPath := TJNet_URI.JavaClass.parse(StringToJString('file:///storage/emulated/0/Pictures/img.jpg')); //заносим путь в URIPath DownloadRequest := TJDownloadManager_Request.JavaClass.init(URI); //инициализируем DownloadRequest с ссылкой на файл DownloadRequest.setDestinationUri(URIPath); //Устанавливаем конечный путь в DownloadRequest DownloadPermission := SharedActivityContext.getSystemService //Получаем доступ к сервису загрузки (TJContext.JavaClass.DOWNLOAD_SERVICE); DownloadManager := TJDownloadManager.Wrap(DownloadPermission); //Даём доступ к сервису загрузки DownloadManager'у DownloadManager.enqueue(DownloadRequest); //Запускаем загрузку end; Вот и всё, осталось только процедура нажатия на кнопку
    procedure TForm1.Button1Click(Sender: TObject); begin Download('g1e06713e4c5d9a9c5356f9e481ca8c37a7800ff986743fe4364aef699782e22b6a41f794dfd54ed32783eb0a577dc21b4dd2ba8fd83b6722740285291263d718'); end; Теперь можно компилировать программу и проверить, работает-ли она. Если всё сработало, то в директории Pictures должен появиться файл "img.jpg", содержащий в себе изображение тюльпанов.
    Надеюсь, это Вам поможет, если у Вас будут проблемы с загрузкой файлов. Удачи в проектах!
    File Downloading.7z
  6. Like
    PowerOwl получил реакцию от Ingalime в [TWebBrowser] Можно ли получить доступ к элементам разметки страницы HTML?   
    Если я правильно понял, то
    .. uses System.Net.URLClient, System.Net.HttpClient, System.Net.HttpClientComponent; .. procedure Button1.Click(Sender:TObject); begin Memo1.lines.LoadFromStream(NetHTTPClient1.Get('http://yoursite.com/').ContentStream); end;  
  7. Thanks
    PowerOwl отреагировална Axbor в Диалоговое окно на Андроид.   
    Хотел бы поделиться опытом. Рассмотрим случай, когда вам необходимо использовать кастомное диалоговое окно с затемнением. Вроде вот такого:
    Первое, что приходит в голову, это использование Rectangle’ов. Но такой подход показался мне очень сложным, и я нашёл другой способ (многие о нём уже знают) создания кастомного окна.
    Сам способ:
    Создаем вторую форму, и изменяем следующие свойства:
    Transparency = True Fill->Color = #78000000 Fill->Kind = Solid Поместим туда один TLayout, выставим свойство «Align» в значение «Center». И зададим нужный размер. Потом кидаем на TLayout компонент «TRectangle» со свойством «Align – Content». Чтобы TLayout не мешался во время design-time, присвоим свойству Locked значение True. Кидаем остальные компоненты, чтобы получить окно нужного нам вида.
    В итоге у меня получилась вот такая иерархия компонентов:

    Компонент TRectAnimation используем для анимирования процесса появления окна. Вы можете придумать свою анимацию. В данном случае анимируется свойства формы «Padding».
    Напишем следующий код, для того, чтобы при клике на тёмную область формы окно закрылось (событие формы OnTap работает на сенсорных экранах, если вам нужен OnClick тогда воспользуйтесь Layout’ми или Rectangle’ми):
    void __fastcall TForm2::FormTap(TObject *Sender, const TPointF &Point) { Close(); } Вот и всё. К сообщению, я приложил демо приложение с примером такого окна.
    У администраторов просил бы поправить допущенные ошибки так как я не владею русским языком очень хорошем уровне. Или же добавит кое какие дополнительные информации ссылки и т.д.
      Demo.zip
  8. Thanks
    PowerOwl отреагировална Евгений Корепов в Helper для TBitmap - асинхронная загрузка картинки из URL   
    Пока тестировал хелпер в боевом проекте он потихоньку оброс исрпавлениями/улучшениями:
    Загрузка из потока сделана через TBitmapSurface - это позволяет избежать множества глюков. LoadFromStream вынесен из Synchronize (основного потока) в поток HTTPClient - по результатам бенчмарка операция оказалась самая жручая. После исправления интерфейс перестал залипать совсем. Добавлен overload вариант с передачей в процедуру TListItemImage - для использования в TListView и корректной перерисовки подгруженных картинок через AListItemImage.Invalidate. unit BitmapAsyncLoader; interface uses FMX.Graphics, FMX.Surfaces, System.Net.HttpClient, System.Types, System.Classes, FMX.ListView.Types, FMX.ListView.Appearances; type TBitmapAsyncLoader = class helper for TBitmap procedure LoadFromURLAsync(const AUrl : String); overload; procedure LoadFromURLAsync(const AUrl : String; const AListItemImage : TListItemImage); overload; end; implementation var AHTTPClient : THTTPClient; procedure TBitmapAsyncLoader.LoadFromURLAsync(const AURL : String); begin try AHTTPClient.BeginGet( procedure (const ASyncResult: IAsyncResult) var AHTTPResponse : IHTTPResponse; ABitmapSurface : TBitmapSurface; begin if Not ASyncResult.IsCompleted then exit; try AHTTPResponse:=THTTPClient.EndAsyncHTTP(ASyncResult); except end; if Assigned(AHTTPResponse) and (AHTTPResponse.StatusCode = 200) then begin ABitmapSurface:=TBitmapSurface.Create; if TBitmapCodecManager.LoadFromStream(AHTTPResponse.ContentStream, ABitmapSurface, CanvasClass.GetAttribute(TCanvasAttribute.MaxBitmapSize)) then TThread.Synchronize(Nil, procedure begin if Assigned(Self)then Assign(ABitmapSurface); ABitmapSurface.Free; end ) else ABitmapSurface.Free; end; end, AURL ); except end; end; procedure TBitmapAsyncLoader.LoadFromURLAsync(const AURL : String; const AListItemImage : TListItemImage); begin try AHTTPClient.BeginGet( procedure (const ASyncResult: IAsyncResult) var AHTTPResponse : IHTTPResponse; ABitmapSurface : TBitmapSurface; begin if Not ASyncResult.IsCompleted then exit; try AHTTPResponse:=THTTPClient.EndAsyncHTTP(ASyncResult); except end; if Assigned(AHTTPResponse) and (AHTTPResponse.StatusCode = 200) then begin ABitmapSurface:=TBitmapSurface.Create; if TBitmapCodecManager.LoadFromStream(AHTTPResponse.ContentStream, ABitmapSurface, CanvasClass.GetAttribute(TCanvasAttribute.MaxBitmapSize)) then TThread.Synchronize(Nil, procedure begin if Assigned(Self) and Assigned(AListItemImage) then begin AListItemImage.BeginUpdate; Assign(ABitmapSurface); AListItemImage.Invalidate; AListItemImage.EndUpdate; end; ABitmapSurface.Free; end ) else ABitmapSurface.Free; end; end, AURL ); except end; end; initialization AHTTPClient:=THTTPClient.Create; finalization if Assigned(AHTTPClient) then AHTTPClient.DisposeOf; end. Тестовый проект, на этот раз с ListView (по кнопке добавляется 100 итемов) прилагаю.
    BitmapAsyncLoaderListView.7z
  9. Thanks
    PowerOwl отреагировална Евгений Корепов в Helper для TBitmap - асинхронная загрузка картинки из URL   
    Для одного своего проекта сделал, поделюсь, вдруг кому пригодится. Тестировал под Windows и Android.
    Для использования просто добавьте BitmapAsyncLoader в uses, а дальше все просто:
    ImageControl.Bitmap.LoadFromURLAsync('https://bipbap.ru/wp-content/uploads/2017/10/0_8eb56_842bba74_XL-640x400.jpg'); Код юнита хелпера:
    unit BitmapAsyncLoader; interface uses FMX.Graphics, System.Net.HttpClient, System.Types, System.Classes; type TBitmapAsyncLoader = class helper for TBitmap procedure LoadFromUrlAsync(const AUrl : String); end; implementation var AHTTPClient : THTTPClient; procedure TBitmapAsyncLoader.LoadFromURLAsync(const AURL : String); begin try AHTTPClient.BeginGet( procedure (const ASyncResult: IAsyncResult) var AHTTPResponse : IHTTPResponse; begin if Not ASyncResult.IsCompleted then exit; try AHTTPResponse:=THTTPClient.EndAsyncHTTP(ASyncResult); except end; if Assigned(AHTTPResponse) and (AHTTPResponse.StatusCode = 200) then TThread.Synchronize(Nil, procedure begin try Self.LoadFromStream(AHTTPResponse.ContentStream); except end; end ); end, AURL ); except end; end; initialization AHTTPClient:=THTTPClient.Create; finalization if Assigned(AHTTPClient) then begin AHTTPClient.DisposeOf; end; end. Архив с тестовым проектом прилагаю.
    BitmapAsyncLoader.7z
  10. Like
    PowerOwl получил реакцию от Ingalime в Firemonkey и обои рабочего стола   
    Оставлю тут код демо-проекта и обёртку для WallpaperManager, кому-нибудь в будущем пригодятся.
    // Подключить System.IOUtils, Androidapi.JNI.GraphicsContentViewText, // Androidapi.JNI.JavaTypes, // Androidapi.helpers, android.app.WallpaperManager; (android.app.WallpaperManager распаковать и закинуть к исходникам проекта) //перейти в Project->Options->Application->Uses permissions и поставить галочку напротив пункта "Set wallpaper" procedure TForm1.Button1Click(Sender: TObject); var path: string; str: JString; Wallpaper: JWallpaperManager; Image: JBitmap; Context: JContext; begin if Edit1.Text <> '' then begin path := Tpath.Combine(Tpath.GetDocumentsPath, Edit1.Text); //Вместо TPath.GetDocumentsPath можно написать путь к любой директории на //устройстве, вместо Edit1.text - название картинки(с расширением, важно соблюдать регистр!!!) str := StringToJString(path); Context := SharedActivityContext; try if FileExists(path) then begin ShowMessage('Файл найден'); Image := TJBitmapFactory.JavaClass.decodeFile(str) end else ShowMessage('Файл не найден'); except ShowMessage('Не удалось декодировать'); end; try Wallpaper := TJWallpaperManager.JavaClass.getInstance(Context); Wallpaper.setBitmap(Image); except ShowMessage('Не удалось установить обои'); end; end; end;  
    android.app.WallpaperManager.pas.7z
  11. Like
    PowerOwl получил реакцию от Andrey Efimov в Firemonkey и обои рабочего стола   
    Оставлю тут код демо-проекта и обёртку для WallpaperManager, кому-нибудь в будущем пригодятся.
    // Подключить System.IOUtils, Androidapi.JNI.GraphicsContentViewText, // Androidapi.JNI.JavaTypes, // Androidapi.helpers, android.app.WallpaperManager; (android.app.WallpaperManager распаковать и закинуть к исходникам проекта) //перейти в Project->Options->Application->Uses permissions и поставить галочку напротив пункта "Set wallpaper" procedure TForm1.Button1Click(Sender: TObject); var path: string; str: JString; Wallpaper: JWallpaperManager; Image: JBitmap; Context: JContext; begin if Edit1.Text <> '' then begin path := Tpath.Combine(Tpath.GetDocumentsPath, Edit1.Text); //Вместо TPath.GetDocumentsPath можно написать путь к любой директории на //устройстве, вместо Edit1.text - название картинки(с расширением, важно соблюдать регистр!!!) str := StringToJString(path); Context := SharedActivityContext; try if FileExists(path) then begin ShowMessage('Файл найден'); Image := TJBitmapFactory.JavaClass.decodeFile(str) end else ShowMessage('Файл не найден'); except ShowMessage('Не удалось декодировать'); end; try Wallpaper := TJWallpaperManager.JavaClass.getInstance(Context); Wallpaper.setBitmap(Image); except ShowMessage('Не удалось установить обои'); end; end; end;  
    android.app.WallpaperManager.pas.7z
  12. Like
    PowerOwl получил реакцию от Andrey Efimov в Firemonkey и обои рабочего стола   
    Извиняюсь за потраченное время, я сам затупил... У меня клавиатура автоматически переключается в верхний регистр перед началом набора текста, и поэтому программа не могла найти файл. Забыл, что в C-подобных языках регистр имеет значение. В общем, программа работает.
    А что по поводу изучения основ, то я был бы рад их изучить, но не могу найти нигде нормальную(современную) литературу, где доходчиво объясняется использование библиотеки Firemonkey.
    P.S. Я ещё заметил, что у объектов класса JContext есть методы для работы с обоями, но в официальной документации Android сказано, что их вырезали в API Level 15, так что для программирования до Android 4.0 можно обойтись и без WallpaperManager
  13. Like
    PowerOwl получил реакцию от Andrey Efimov в Firemonkey и обои рабочего стола   
    Спасибо за замечания, буду пытаться исправляться.
    1) Спасибо, перечитал, разобрался
    2) Приложу обёртку снизу
    3) Я не могу понять, где взять Context для этого метода. В Java-примерах для его получения используют функцию getContext(), но в Firemonkey такой нет.
    unit android.app.WallpaperManager; interface uses Androidapi.JNIBridge, Androidapi.JNI.GraphicsContentViewText, Androidapi.JNI.JavaTypes, Androidapi.JNI.Net, Androidapi.JNI.Os, Androidapi.JNI.Util; type // ===== Forward declarations ===== JWallpaperInfo = interface;//android.app.WallpaperInfo JWallpaperManager = interface;//android.app.WallpaperManager // ===== Interface declarations ===== JWallpaperInfoClass = interface(JObjectClass) ['{D1CC9CBB-D53F-4F29-ADA9-DD0BF04B0C86}'] {class} function _GetCREATOR: JParcelable_Creator; cdecl; {class} function init(context: JContext; service: JResolveInfo): JWallpaperInfo; cdecl; {class} function describeContents: Integer; cdecl; {class} procedure dump(pw: JPrinter; prefix: JString); cdecl; {class} function getComponent: JComponentName; cdecl; {class} function getSettingsActivity: JString; cdecl; {class} function loadAuthor(pm: JPackageManager): JCharSequence; cdecl; {class} function loadDescription(pm: JPackageManager): JCharSequence; cdecl; {class} function toString: JString; cdecl; {class} procedure writeToParcel(dest: JParcel; flags: Integer); cdecl; {class} property CREATOR: JParcelable_Creator read _GetCREATOR; end; [JavaSignature('android/app/WallpaperInfo')] JWallpaperInfo = interface(JObject) ['{A357E89F-3891-4795-8207-B1416424D512}'] function getPackageName: JString; cdecl; function getServiceInfo: JServiceInfo; cdecl; function getServiceName: JString; cdecl; function loadIcon(pm: JPackageManager): JDrawable; cdecl; function loadLabel(pm: JPackageManager): JCharSequence; cdecl; function loadThumbnail(pm: JPackageManager): JDrawable; cdecl; end; TJWallpaperInfo = class(TJavaGenericImport<JWallpaperInfoClass, JWallpaperInfo>) end; JWallpaperManagerClass = interface(JObjectClass) ['{F16EBFA1-4C27-4869-BEAA-3112EC3303A9}'] {class} function _GetACTION_CHANGE_LIVE_WALLPAPER: JString; cdecl; {class} function _GetACTION_CROP_AND_SET_WALLPAPER: JString; cdecl; {class} function _GetACTION_LIVE_WALLPAPER_CHOOSER: JString; cdecl; {class} function _GetCOMMAND_DROP: JString; cdecl; {class} function _GetCOMMAND_SECONDARY_TAP: JString; cdecl; {class} function _GetCOMMAND_TAP: JString; cdecl; {class} function _GetEXTRA_LIVE_WALLPAPER_COMPONENT: JString; cdecl; {class} function _GetWALLPAPER_PREVIEW_META_DATA: JString; cdecl; {class} procedure clear; cdecl;//Deprecated {class} function getBuiltInDrawable(outWidth: Integer; outHeight: Integer; scaleToFit: Boolean; horizontalAlignment: Single; verticalAlignment: Single): JDrawable; cdecl; overload; {class} function getCropAndSetWallpaperIntent(imageUri: Jnet_Uri): JIntent; cdecl; {class} function getDesiredMinimumHeight: Integer; cdecl; {class} function getInstance(context: JContext): JWallpaperManager; cdecl; {class} function getWallpaperInfo: JWallpaperInfo; cdecl; {class} function hasResourceWallpaper(resid: Integer): Boolean; cdecl; {class} procedure sendWallpaperCommand(windowToken: JIBinder; action: JString; x: Integer; y: Integer; z: Integer; extras: JBundle); cdecl; {class} procedure setBitmap(bitmap: JBitmap); cdecl; {class} procedure setResource(resid: Integer); cdecl; {class} procedure setWallpaperOffsets(windowToken: JIBinder; xOffset: Single; yOffset: Single); cdecl; {class} procedure suggestDesiredDimensions(minimumWidth: Integer; minimumHeight: Integer); cdecl; {class} property ACTION_CHANGE_LIVE_WALLPAPER: JString read _GetACTION_CHANGE_LIVE_WALLPAPER; {class} property ACTION_CROP_AND_SET_WALLPAPER: JString read _GetACTION_CROP_AND_SET_WALLPAPER; {class} property ACTION_LIVE_WALLPAPER_CHOOSER: JString read _GetACTION_LIVE_WALLPAPER_CHOOSER; {class} property COMMAND_DROP: JString read _GetCOMMAND_DROP; {class} property COMMAND_SECONDARY_TAP: JString read _GetCOMMAND_SECONDARY_TAP; {class} property COMMAND_TAP: JString read _GetCOMMAND_TAP; {class} property EXTRA_LIVE_WALLPAPER_COMPONENT: JString read _GetEXTRA_LIVE_WALLPAPER_COMPONENT; {class} property WALLPAPER_PREVIEW_META_DATA: JString read _GetWALLPAPER_PREVIEW_META_DATA; end; [JavaSignature('android/app/WallpaperManager')] JWallpaperManager = interface(JObject) ['{A1B98FC3-5736-43BC-A41C-5588DC0D8838}'] procedure clearWallpaperOffsets(windowToken: JIBinder); cdecl; procedure forgetLoadedWallpaper; cdecl; function getBuiltInDrawable: JDrawable; cdecl; overload; function getDesiredMinimumWidth: Integer; cdecl; function getDrawable: JDrawable; cdecl; function getFastDrawable: JDrawable; cdecl; function isWallpaperSupported: Boolean; cdecl; function peekDrawable: JDrawable; cdecl; function peekFastDrawable: JDrawable; cdecl; procedure setStream(data: JInputStream); cdecl; procedure setBitmap(bitmap: JBitmap); cdecl; procedure setWallpaperOffsetSteps(xStep: Single; yStep: Single); cdecl; end; TJWallpaperManager = class(TJavaGenericImport<JWallpaperManagerClass, JWallpaperManager>) end; implementation procedure RegisterTypes; begin TRegTypes.RegisterType('android.app.WallpaperManager.JWallpaperInfo', TypeInfo(android.app.WallpaperManager.JWallpaperInfo)); TRegTypes.RegisterType('android.app.WallpaperManager.JWallpaperManager', TypeInfo(android.app.WallpaperManager.JWallpaperManager)); end; initialization RegisterTypes; end.  
×
×
  • Создать...