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

Andrey Efimov

Модераторы
  • Постов

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

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

    123

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

  1. Like
    Andrey Efimov отреагировална PowerOwl в Android 10 и муз.плеер   
    У меня, кстати, появилось предположение, почему прога запустилась у меня на Android 10, но на Android 6.0.1 и у Олега Киреева на Android 10 - нет. Возможно, это связано с тем, что Вы скомпилировали приложение только под Android 64. У моего телефона процессор 64-разрядный(Samsung Exynos 7 Octa(5433)), но, как сказала Aida64, 32-bit Mode. У Олега Киреева процессор Samsung Exynos 7 Octa 7870, тоже 64-разрядный, но, поскольку разница между датами выхода чипов всего 2 года, то, возможно, он тоже работает в 32-битном режиме.  На Нокиа 3.1, на которой всё работало, стоит 64-разрядный Mediatek MT6750n. Сейчас ещё проверю на Самсунг Ноут 10+ с чипом Qualcomm Snapdragon 855 в 64-разрядном режиме.
    Вот тут было обсуждение по поводу устройства на базе такого же чипа, как у Олега, где оказалось, что ЦПУ поддерживает 64-битные инструкции, но прошивка - нет: https://stackoverflow.com/questions/49184689/why-does-my-android-device-with-armv8-based-cpu-cores-exynos-7-octa-7870-not-s
  2. Like
    Andrey Efimov получил реакцию от Ingalime в Android 10 и муз.плеер   
    Скриншот Deployment Manager'а в "студию" (для 32 и 64 битной версии). Отсортируйте по столбцу Local Name.
  3. Like
    Andrey Efimov получил реакцию от Tumaso в Android 10 и муз.плеер   
    У меня на устройстве с Андроид 11 и эмуляторе с Андроид 7.1.2 приложение не падает.

    По теме, делайте дебаг версию и ищите устройство на котором падает, запускайте monitor.bat и приложение, снимайте логи и выкидывайте их сюда. Это нужно сделать как минимум для того чтобы убедиться в ваших догадках (что происходит падение из-за сервиса). Так же попробуйте вынести в кнопку код запуска сервиса.
    Документация по Foreground service: https://developer.android.com/guide/components/foreground-services
     
     
  4. Thanks
    Andrey Efimov получил реакцию от Ingalime в Android 10 и муз.плеер   
    У меня на устройстве с Андроид 11 и эмуляторе с Андроид 7.1.2 приложение не падает.

    По теме, делайте дебаг версию и ищите устройство на котором падает, запускайте monitor.bat и приложение, снимайте логи и выкидывайте их сюда. Это нужно сделать как минимум для того чтобы убедиться в ваших догадках (что происходит падение из-за сервиса). Так же попробуйте вынести в кнопку код запуска сервиса.
    Документация по Foreground service: https://developer.android.com/guide/components/foreground-services
     
     
  5. Like
    Andrey Efimov получил реакцию от PowerOwl в Android 10 и муз.плеер   
    У меня на устройстве с Андроид 11 и эмуляторе с Андроид 7.1.2 приложение не падает.

    По теме, делайте дебаг версию и ищите устройство на котором падает, запускайте monitor.bat и приложение, снимайте логи и выкидывайте их сюда. Это нужно сделать как минимум для того чтобы убедиться в ваших догадках (что происходит падение из-за сервиса). Так же попробуйте вынести в кнопку код запуска сервиса.
    Документация по Foreground service: https://developer.android.com/guide/components/foreground-services
     
     
  6. Thanks
    Andrey Efimov получил реакцию от Ingalime в Android 10 и муз.плеер   
    Есть два варианта:
    1) Добавить в промежуточном манифесте (находится тут: Project\Android\Debug\AndroidManifest.xml)
    Находим:
    <service android:exported="false" android:name="com.embarcadero.services.serPublic" /> Заменяем на:
    <service android:exported="false" android:foregroundServiceType="mediaPlayback" android:name="com.embarcadero.services.serPublic" /> Делаем деплой проекта.
     
    2) Прописать сервис в шаблоне (находится тут: Project\AndroidManifest.template.xml)
    Примерно вот так.
    Находим:
    <%services%> Заменяем на:
    <service android:exported="false" android:foregroundServiceType="mediaPlayback" android:name="com.embarcadero.services.serPublic" /> <service android:exported="false" android:name="com.embarcadero.firebase.messaging.ProxyFirebaseMessagingService"> <intent-filter> <action android:name="com.google.firebase.MESSAGING_EVENT" /> </intent-filter> </service> <service android:exported="true" android:name="com.google.firebase.messaging.FirebaseMessagingService"> <intent-filter android:priority="-500"> <action android:name="com.google.firebase.MESSAGING_EVENT" /> </intent-filter> </service> <service android:exported="false" android:name="com.google.firebase.components.ComponentDiscoveryService"> <meta-data android:name="com.google.firebase.components:com.google.firebase.iid.Registrar" android:value="com.google.firebase.components.ComponentRegistrar" /> </service> Делаем сборку и деплой.
     
    p.s. Возможно есть ещё способы, я давненько не касался темы сервисов..
  7. Thanks
    Andrey Efimov получил реакцию от slav_z в Прощай, APK. Google переходит на новый формат Android-приложений   
    Android App Bundle Support
  8. Thanks
    Andrey Efimov получил реакцию от gonzales в Прощай, APK. Google переходит на новый формат Android-приложений   
    Android App Bundle Support
  9. Thanks
    Andrey Efimov получил реакцию от Ingalime в Android 10 и муз.плеер   
    <manifest> ... <service ... android:foregroundServiceType="mediaPlayback" /> </manifest> Более подробно можно почитать тут Foreground services - Declare foreground service types
  10. Thanks
    Andrey Efimov получил реакцию от Ingalime в Android 10 и муз.плеер   
    Возможно, для Андроид 10-11, необходимо указывать тип службы. (в манифесте: foregroundServiceType и в startForeground)
  11. Like
    Andrey Efimov отреагировална HelleR в Отправка событий в Firebase Google Analytics - GA4   
    Подключить Firebase не получилось. Напишу по памяти, так как время прошло уже прилично и это мои собственные умозаключения не претендующие на истину.
    Было много различных попыток подключить Firebase , основная проблема, что нет в наличии библиотеки jar, последняя библиотека лежит в maven репозитории и она уже устарела, по-моему от 2019 года. 
    Ссылка на maven репозиторий
    Firebase, да и многие другие предлагают использовать только Gradle, что не дает мне возможность использовать это для Delphi .
    После общения с поддержкой от Firebase (если сильно упростить), мне предложили изменить среду разработки. Но приложение уже было полностью готово для двух мобильных платформ, и мне пришлось искать другие SDK. 
    Я перебрал многие, которые предлагали помимо установки с помощью Gradle, скачать SDK в виде файла jar или aar (из aar иногда можно добыть jar, но это только иногда, например в последних firebase его там нет)
    Забыл сказать, что для всех манипуляций, обязательно нужна установленная и запущенная Android Studio, и подключенный телефон, на который Delphi устанавливает приложение. В Android Studio я собрал проект с таким же именем, как и у моего Delphi приложения, для удобства отладки и контроля логов logcat. В приложение на Android Studio я подключил через Gradle нужное мне SDK и проверил его работоспособность, скопировал логи правильной работы приложения, отследил результаты на сайте аналитики, увидел что они действительно появились, и все данные телефона (размер экрана, марка ...) пришли в аналитику. Включил режим debag на стороне аналитики. 
    Эти действия я проделывал и с Firebase, приложение написанное на Android Studio запускалось без проблем, приложение написанное на Delphi, в силу отсутствия новой библиотеки jar не запускалось и сыпало в logcat целые "простыни" ошибок, никакие данные в аналитику не приходили.
    Я пробовал вытащить нужную мне библиотеку Firebase из собранного в Android Studio dex файла, рабочего приложения. Затем вычленить из него нужные мне файлы и прикрепить их Delphiпроекту в виде jar библиотеки, но появлялась новая проблема, конфликты с уже установленными библиотеками на Delphi, отключение которых уже не позволяло собрать dex файл для Delphi проекта.
    Остановился я на  SDK AppsFlyer, интеграция была возможна, так как сервис предлагал добавление SDK с помощью Gradle и возможность скачать и установить вручную. Саму библиотеку я подключил, но возникла проблема с получением событий, которые приходили например от google play
    Вот пример того что не получилось сделать:
    AppsFlyerConversionListener conversionListener = new AppsFlyerConversionListener() { @Override public void onConversionDataSuccess(Map<String, Object> conversionData) { for (String attrName : conversionData.keySet()) { Log.d("LOG_TAG", "attribute: " + attrName + " = " + conversionData.get(attrName)); } } Эти события, никак не удалось получить, и решить проблему не удалось, информации я не нашел.
    Было принято решение попробовать другое SDK. На этот раз это была Yandex AppMetrica, эта интеграция получилась.
    Для начала у них в доках по интеграции написано что есть возможность скачать jar и что все библиотеки (старые версии мне в дальнейшем тоже пригодились) есть в maven репозитории
    Далее я добавил библиотеку в проект, и приступил к созданию файла моста, для связи 
     

    Вот сама библиотека: com.yandex.androidmobmetricalib3.20.1.jar.7z
    Файл мост я создавал с помощью утилиты java2op, которая находится в ... Embarcadero\Studio\21.0\bin\converters
    Но, при создании я получил ошибку, что-то там дублировалось и что-то мешало. Пытался проделать это с конкретным классом, но ничего не получилось. Оставалось только или делать файл ручками, или надеяться что в одной из старых библиотек все сгенерируется. Эмпирическим методом была найдена старая библиотека, в которой название методов нужного мне класса осталось прежним, а ошибка с дубликатами ушла.
    Файл мост был создан. Android.JNI.Yandex.pas.7z
    Осталось подключить его к моему приложению. Был создан класс, который работал с нужными мне методами SDK Yandex аналитики (Android.JNI.Yandex):
    unit YandexAnalytics; interface uses System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants, {$IFDEF ANDROID} Android.JNI.Yandex, Androidapi.Helpers, Androidapi.JNI.JavaTypes, Androidapi.JNI.GraphicsContentViewText, Androidapi.JNI.Os, Androidapi.JNI.App, {$ENDIF} FMX.Types; type TYandexMetrica = class private public {$IFDEF ANDROID} YAC : JYandexMetricaConfig; YA : JYandexMetrica; {$ENDIF} constructor Create; procedure SendEvent(Category, Action, LabelName : String; LabelValue : Integer); end; implementation constructor TYandexMetrica.Create; var AnKey, AnRepKey : JString; begin try AnKey := StringToJString('86e64a77-XXXX-XXXX-XXXX-XXXXXXXcbbc'); AnRepKey := StringToJString('20799a27-XXXX-XXXX-XXXX-XXXXXXX14180'); YAC := TJYandexMetricaConfig.JavaClass.newConfigBuilder(AnKey).withLogs().build; YA := TJYandexMetrica.Create; TJYandexMetrica.JavaClass.activate(TAndroidHelper.Context, YAC); TJYandexMetrica.JavaClass.enableActivityAutoTracking( TAndroidHelper.Activity.getApplication ); Log.d('================= TYandexMetrica.Created ======================'); EXCEPT on E : Exception do Begin Log.d( E.ClassName + 'YandexMetrica.Create -> ' + E.Message ); End; END; end; procedure TYandexMetrica.SendEvent(Category, Action, LabelName : String; LabelValue : Integer); begin {$IFDEF ANDROID} try Log.d( 'TRY YandexMetrica.SendEvent -> ' + Category + ',' + Action + ',' + LabelName + ',' + LabelValue.ToString ); TJYandexMetrica.JavaClass.reportEvent(StringToJString(Category), StringToJString('{"Action":"' + Action + '", "LabelName":"' + LabelName + '", "LabelValue":"' + LabelValue.ToString + '"}')); Log.d('================= Event Sended ======================'); EXCEPT on E : Exception do Begin Log.d( E.ClassName + 'YandexMetrica.SendEvent -> ' + E.Message ); End; END; {$ENDIF} end; end. В событии приложения onCreate создал  экземпляр класса, и отправил событие
     
    YA := TYandexMetrica.Create; YA.SendEvent('AppEvent','Started',User.Client_Id, 0);  
    Было добавлено в файл AndroidManifest.template.xml (информация из яндекс документов по интеграции)
    <%services%> <service android:name="com.yandex.metrica.MetricaService" android:enabled="true" android:exported="true" android:process=":Metrica"> <intent-filter> <category android:name="android.intent.category.DEFAULT" /> <action android:name="com.yandex.metrica.IMetricaService" /> <data android:scheme="metrica" /> </intent-filter> <meta-data android:name="metrica:api:level" android:value="16" /> </service> <receiver android:name="com.yandex.metrica.MetricaEventHandler" android:enabled="true" android:exported="true"> <intent-filter> <action android:name="com.yandex.metrica.intent.action.SYNC" /> </intent-filter> <intent-filter> <action android:name="android.intent.action.PACKAGE_ADDED" /> <action android:name="android.intent.action.PACKAGE_DATA_CLEARED" /> <data android:scheme="package" /> </intent-filter> <!-- Необходимо для трэкинга кампаний --> <intent-filter> <action android:name="com.android.vending.INSTALL_REFERRER" /> </intent-filter> </receiver> Пример логов из logcat, из которых видно что библиотека инициализирована, и отправлены два события [AppEvent] и [Balance]
    2021-07-01 14:02:17.108 15138-15168/? I/AppMetrica: [ru.yandex.mobile.appmetrica] : [27889a6e-xxxx-xxxx-xxxx-xxxxxxxx3c64] Initializing of Metrica, Release type, Version 3.5.3, API Level 76, Dated 30.01.2019. 2021-07-01 14:58:48.979 18460-18460/? I/AppMetrica: Initializing of Metrica, Release type, Version 3.20.1, API Level 94, Dated 14.04.2021. 2021-07-01 14:58:49.033 18460-18531/? I/AppMetrica: Activate AppMetrica with APIKey 86e64a77-xxxx-xxxx-xxxx-xxxxxxxxcbbc 2021-07-01 14:58:49.033 18460-18531/? I/AppMetrica: [com.soclikes_ig] : [86e64a77-xxxx-xxxx-xxxx-xxxxxxxxcbbc] Enable activity auto tracking 2021-07-01 14:58:49.033 18460-18531/? I/AppMetrica: [com.soclikes_ig] : [86e64a77-xxxx-xxxx-xxxx-xxxxxxxxcbbc] Event received: AppEvent. With value: {"Action":"Started", "LabelName":"2905202123125", "LabelValue":"0"} 2021-07-01 14:58:49.034 18460-18531/? I/AppMetrica: Activate reporter with APIKey 20799a27-xxxx-xxxx-xxxx-xxxxxxxx4180 2021-07-01 14:58:49.233 18542-18567/? I/AppMetrica: Initializing of Metrica, Release type, Version 3.20.1, API Level 94, Dated 14.04.2021. 2021-07-01 14:58:49.263 18542-18567/? I/AppMetrica: Activate reporter with APIKey 20799a27-xxxx-xxxx-xxxx-xxxxxxxx4180 2021-07-01 14:59:13.975 18460-18531/? I/AppMetrica: [com.soclikes_ig] : [86e64a77-xxxx-xxxx-xxxx-xxxxxxxxcbbc] Event received: AppEvent. With value: {"Action":"ProfilesDeleted", "LabelName":"alex", "LabelValue":"319"} 2021-07-01 14:59:31.368 18460-18531/? I/AppMetrica: [com.soclikes_ig] : [86e64a77-xxxx-xxxx-xxxx-xxxxxxxxcbbc] Event received: Balance. With value: {"Action":"TrStart", "LabelName":"2905202123125", "LabelValue":"3"}  
    Вот такие данные пришли в аналитику. +1 пользователь

     
    +2 события

     
     
     
  12. Like
    Andrey Efimov получил реакцию от Ingalime в Firemonkey и обои рабочего стола   
    Отлично.
    Вот ещё один момент, на эмуляторе с рут-правами и обычным перекидыванием файлов в директорию может появляться эта же ошибка. Видимо, это связано с правами на директорию, поэтому, чтобы ошибки не было, необходимо добавить необходимые файлы в проект через деплой (Deployment Manager).
     
    По поводу книг, загляните сюда https://delphifmandroid.blogspot.com/p/blog-page_15.html, ещё полезное можно найти тут https://blogs.embarcadero.com/. Тут - https://www.youtube.com/watch?v=Q6vXbXFthLU&list=PLvs4_U1JSz61q3b-S1KcX4F5rbWPAEWsH , Ярослав выложил курс по стилям. И вот сюда - https://learndelphi.org/
     
    P.s. Студия не поддерживает разработку под версии Андроида ниже 5.1. http://docwiki.embarcadero.com/RADStudio/Sydney/en/Android_Devices_Supported_for_Application_Development
  13. Like
    Andrey Efimov отреагировална PowerOwl в 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
  14. Like
    Andrey Efimov отреагировална PowerOwl в Firemonkey и обои рабочего стола   
    Извиняюсь за потраченное время, я сам затупил... У меня клавиатура автоматически переключается в верхний регистр перед началом набора текста, и поэтому программа не могла найти файл. Забыл, что в C-подобных языках регистр имеет значение. В общем, программа работает.
    А что по поводу изучения основ, то я был бы рад их изучить, но не могу найти нигде нормальную(современную) литературу, где доходчиво объясняется использование библиотеки Firemonkey.
    P.S. Я ещё заметил, что у объектов класса JContext есть методы для работы с обоями, но в официальной документации Android сказано, что их вырезали в API Level 15, так что для программирования до Android 4.0 можно обойтись и без WallpaperManager
  15. Like
    Andrey Efimov отреагировална PowerOwl в 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.  
  16. Like
    Andrey Efimov получил реакцию от Ingalime в Firemonkey и обои рабочего стола   
    Ну смотрите:
    1) Как я уже говорил, вам необходимо ознакомиться с основами транслирования и использования АПИ.
    Например тут: Как создавать обёртки для JAVA-кода и тут: Как подключить и использовать свой JAVA-класс (статьи "малость" старые, но суть сохранилась.)
    Единственное, что могу добавить (про обёртки):
    Всё, что находится в interface(JObjectClass) вызывается так: TJНазваниекласса.JavaClass.НазваниеМетода/Поля
    Всё, что находится в interface(JObject) вызывается только через предварительно созданный/полученный объект.
     
    2) На форуме, для кода используйте тег "Код", без подсветки кода (или как вам угодно). Это помогает повысить читабельность поста, отделить код от текста. Если вы используете обёртку не из стандартной поставки, то прикладывайте её к посту. Не редкость, что ошибки бывают в самих обёртках.
    3) Из-за первого пункта вы начали копировать другие решения (не обдумывая). Я буду исходить из вашего изначального кода.
    Вам должно быть достаточно подключения AndroidAPI.JNI.GraphicsContentViewText, там всё уже реализовано (это я про обёртку для использования JBitmap и JBitmapFactory).
    Далее моё "гадание на кофейной гуще" (т.к. обёртку для WallpaperManager в вашем сообщении я не вижу).
    Исхожу из того, что она сгенерирована правильно. Значит в вашем коде, перед использованием метода setBitmap(Image); необходимо получить доступ к объекту WallpaperManager. Заходим по ссылке Android API: WallpaperManager, смотрим на описание и методы, видим метод Android API: WallpaperManager#getInstance, делаем вывод, что с помощью этого метода сможем получить доступ к объекту WallpaperManager, а далее попытаться использовать метод setBitmap. На этом, моё предсказание завершено (само собой не факт, что оно верное, но если бы передо мной стояла такая задача, то в самом начале, я поступил бы именно так), остаётся только попробовать.
     
     
    p.s. Автоматический генератор обёрток иногда сбоит, рекомендую всегда проверять генерируемые обёртки. Результаты этих сбоев встречались как в личном опыте, так и у других разработчиков на форуме.
  17. Like
    Andrey Efimov получил реакцию от Ingalime в Firemonkey и обои рабочего стола   
    Используйте вот такое обращение к этому методу
    Image := TJBitmapFactory.JavaClass.decodeFile(str);  
  18. Like
    Andrey Efimov получил реакцию от Ingalime в Firemonkey и обои рабочего стола   
    Для стандартного АПИ, в большинстве случаев, достаточно иметь только обёртку (.pas файл).
    Какая то часть обёрток для АПИ всегда идёт со студией в комплекте (найти можно тут: C:\Program Files (x86)\Embarcadero\Studio\версиястудии\source\).
    Если нужной вам обёртки нет в комплекте со студией, то либо генерите её самостоятельно, либо скачиваете с GitHub'а. На форуме есть упоминание об этом: Полностью транслированное Android API 7-23 уровня
    Для сторонних jar - библиотек, необходимо иметь саму библиотеку в виде jar файла и обёртку к ней.
     
    В вашем случае, должно хватить (если не брать во внимание callback OnColorsChangedListener) простого указания .pas файла в секции uses вашего приложения.
     
    p.s. Все начальные вопросы уже много раз обсуждались на форуме и в различных блогах, ищите, читайте, пробуйте
    p.s.2. Можете "покопаться", например, тут (https://delphifmandroid.blogspot.com/p/blog-page_27.html), тут (https://github.com/AndrewEfimov) и тут (http://yaroslavbrovin.ru/). Ну и конечно же, если вы хотите использовать специфичные функции Андроида, то необходимо ознакомиться https://developer.android.com
  19. Like
    Andrey Efimov получил реакцию от Ingalime в Не запускается служба   
    Значит вы не правильно собрали приложение. Этот apk файл собран в "RAD Studio 10.2 Tokyo Release 2 (без фиксов)" только что и протестирован на Андроид 4.4.2 (что под рукой было...).
  20. Like
    Andrey Efimov получил реакцию от Ingalime в Delphi 10.4.1 и Андроид 11   
    К сожалению, статья (перевод), которую вы рекомендуете, опубликована в закрытом разделе (для пользователей с подпиской FGX Native).
     
    Человек мог просто не знать/не заметить про особенность, озвученную выше.
     
    Вот тут можно прочитать оригинал статьи (на английском): https://quality.embarcadero.com/browse/RSP-27218
     
  21. Like
    Andrey Efimov отреагировална brunnengi в Android 10 (API уровня 29)   
    Здравствуйте.
    Некоторые пользователи Delphi 10.3 столкнулись с тем что даже при указании SDK 29 в манифесте проекта, при запуске скомпилированного приложения на платформе Android 10 происходило его падение.
    В августе 30 числа 2020 года было дано решение как пофиксить эту проблему.
    Переход на версию Delphi 10.4 не для всех является приемлемым решением, по разным причинам, к примеру у кого то платные компоненты и нет возможности обновиться до актуальных версий.
    Ниже представлен перевод статьи. В конце будет ссылка на оригинал.
    Приведенное здесь решение нацелено на обновление функции 'dlopen' в файле 'ICU.inc' (он включен в файл 'System.pas'). Вот шаги, необходимые для решения указанной проблемы:
    Откройте проводник и перейдите в папку по следующему пути: C:\Program Files (x86)\Embarcadero\Studio\20.0\source Скопируйте файлы из архива "missing_source_files.zip", который приложен в посту, в папку source из пункта "1" (комментарий от переводчика: в "missing_source_files.zip" лежит папка "rtl" в которой две папки - "posix", "sys". Лично я сделал сначала backup папки rtl из папки source, что и вам советую. Затем скопировал rtl папку из "missing_source_files.zip" и вставил в папку source) Переходим по пути: C:\Program Files (x86)\Embarcadero\Studio\20.0\source\rtl\sys Открываем файл "ICU.inc" в текстовом редакторе (пожалуйста, сделайте backup файла 'ICU.inc' для пущей безопасности). (комментарий от переводчика: орудовать в этой папке без прав админа не вариант. Поэтому я советую сначала скопировать файл "ICU.inc" куда нибудь в другое место, к примеру в папку Documents и там уже открыть его в том же Блокноте и сделав необходимые изменения сохранить файл и затем уже переместить его в C:\Program Files (x86)\Embarcadero\Studio\20.0\source\rtl\sys с заменой) В текстовом редакторе надо изменить функцию InitICU:
    Было вот так: А сделать надо что было вот так:
     


     
    Сохраняем сделанные изменения в файле "ICU.inc"
    Возвращаемся в проводник и переходим в папку %USERPROFILE%
    Скопируйте файл "build.bat" из архива "build_script.zip" , который приложен в этому посту в папку из пункта 7.
    Запустите от имени Администратора файл "build.bat". (Он создаст папку %USERPROFILE%\build в которой будет несколько папок с файлами. Из них нам нужны будут только System.o, но об этом ниже)
    Возвращаемся в проводник и переходим в папку C:\Program Files (x86)\Embarcadero\Studio\20.0\lib\android\debug
    Скопируйте файл "System.o" из папки %USERPROFILE%\build\android\debug в папку из шага 10 (не забывайте сделать backup всех файл что вы заменяете, на всякий случай).
    Теперь переходим в проводник в папку C:\Program Files (x86)\Embarcadero\Studio\20.0\lib\android\release
    Скопируйте файл "System.o" из папки %USERPROFILE%\build\android\release в папку из шага 12 (не забывайте сделать backup всех файл что вы заменяете, на всякий случай).
    Переходим в проводник в папку C:\Program Files (x86)\Embarcadero\Studio\20.0\lib\android64\debug
    Скопируйте файл "System.o" из папки %USERPROFILE%\build\android64\debug  в папку из шага 14 (не забывайте сделать backup всех файл что вы заменяете, на всякий случай).
    Переходим в проводник в папку C:\Program Files (x86)\Embarcadero\Studio\20.0\lib\android64\release
    Скопируйте файл "System.o" из папки %USERPROFILE%\build\android64\release в папку из шага 16 (не забывайте сделать backup всех файл что вы заменяете, на всякий случай).
     
    На этом всё. Автор данного перевода лично прошел по всем шагам и сделал всё как было сказано, а также протестил на приложении что уже было в PlayMarket'е но не запускалось под Android 10. Я его обновил и запустил как на Android ниже 10, так и на Android 10. 

    ЕСЛИ ВЫ НЕ ДОВЕРЯЕТЕ ПЕРЕВОДУ И/ИЛИ ВЫЛОЖЕННЫМ ФАЙЛАМ, ТО НИЖЕ ДАНА ССЫЛКА НА ОРИГИНАЛ СТАТЬИ
    // файлы выложенные здесь, взяты с форума где оригинал статьи.

    Ссылка на оригинал https://quality.embarcadero.com/browse/RSP-27218
    Если нет логина, то под споллером скрины экрана с форума ссылки выше:
     
     
    Отдельное спасибо пользователю Stanislau Ihnatovich за сообщение в Telegram о том что есть решение
     
    build_script.zipmissing_source_files.zip
     
  22. Like
    Andrey Efimov получил реакцию от Евгений Корепов в Работа с android.hardware.usb.UsbManager   
    Попробуйте так:
    var Device: JUsbDeviceConnection; ... Device := FUsbManager.JavaClass.openDevice();  
    p.s. Учитывайте тот факт, что обёртка могла сгенериться неправильно. Java2Op не всегда отрабатывает как надо, поэтому появляется необходимость проверки и правки результата.
    p.s.2. И вроде как у вас как раз такой случай... Попробуйте вот эту:
    JUsbManagerClass = interface(JObjectClass) ['{1048A6E9-E1B5-4DA5-A168-ED91E8DE5284}'] {class} function _GetACTION_USB_ACCESSORY_ATTACHED: JString; cdecl; {class} function _GetACTION_USB_ACCESSORY_DETACHED: JString; cdecl; {class} function _GetACTION_USB_DEVICE_ATTACHED: JString; cdecl; {class} function _GetACTION_USB_DEVICE_DETACHED: JString; cdecl; {class} function _GetEXTRA_ACCESSORY: JString; cdecl; {class} function _GetEXTRA_DEVICE: JString; cdecl; {class} function _GetEXTRA_PERMISSION_GRANTED: JString; cdecl; {class} property ACTION_USB_ACCESSORY_ATTACHED: JString read _GetACTION_USB_ACCESSORY_ATTACHED; {class} property ACTION_USB_ACCESSORY_DETACHED: JString read _GetACTION_USB_ACCESSORY_DETACHED; {class} property ACTION_USB_DEVICE_ATTACHED: JString read _GetACTION_USB_DEVICE_ATTACHED; {class} property ACTION_USB_DEVICE_DETACHED: JString read _GetACTION_USB_DEVICE_DETACHED; {class} property EXTRA_ACCESSORY: JString read _GetEXTRA_ACCESSORY; {class} property EXTRA_DEVICE: JString read _GetEXTRA_DEVICE; {class} property EXTRA_PERMISSION_GRANTED: JString read _GetEXTRA_PERMISSION_GRANTED; end; [JavaSignature('android/hardware/usb/UsbManager')] JUsbManager = interface(JObject) ['{6F603A25-E816-4012-9B23-054B428A4A75}'] function getAccessoryList: TJavaObjectArray<JUsbAccessory>; cdecl;//Deprecated function getDeviceList: JHashMap; cdecl;//Deprecated function hasPermission(device: JUsbDevice): Boolean; cdecl; overload;//Deprecated function hasPermission(accessory: JUsbAccessory): Boolean; cdecl; overload;//Deprecated function openAccessory(accessory: JUsbAccessory): JParcelFileDescriptor; cdecl;//Deprecated function openDevice(device: JUsbDevice): JUsbDeviceConnection; cdecl;//Deprecated procedure requestPermission(device: JUsbDevice; pi: JPendingIntent); cdecl; overload;//Deprecated procedure requestPermission(accessory: JUsbAccessory; pi: JPendingIntent); cdecl; overload;//Deprecated end; TJUsbManager = class(TJavaGenericImport<JUsbManagerClass, JUsbManager>) end;  
    p.s.3. С правилами создания обёртки можно ознакомиться тут https://delphifmandroid.blogspot.com/2014/07/java.html
    Статья старая, но правила связанные с полями/константами и методами действительны по сей день.
  23. Like
    Andrey Efimov отреагировална OnePeople в Android Services   
    Попробуйте еще сделать так
    <uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />        jpn:=TAndroidHelper.Context.getPackageName;
           ps:=TAndroidHelper.Context.getSystemService(TJContext.JavaClass.POWER_SERVICE);
        if ps <> nil then
          begin
          pm := TJPowerManager.Wrap((ps as ILocalObject).GetObjectID);
          end;
         if pm.isIgnoringBatteryOptimizations(jpn)=false then
            begin

             Intent := TJIntent.Create;
              Intent.setAction(TJSettings.JavaClass.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
             intent.setData(TJnet_Uri.JavaClass.parse(StringToJString('package:').concat(jpn)));
             TAndroidHelper.Context.startActivity(Intent);
            end;
     
     
  24. Like
    Andrey Efimov отреагировална OnePeople в Android Services   
    И нужно внимательно читать справку гууууугл

  25. Thanks
    Andrey Efimov получил реакцию от Ingalime в Android Services   
    Всё возможно...
    В данном случае, у Джима код отрабатывал как ожидается, по причине того (я предполагаю), что он тестировал его на Nexus 5 (2015 чистый Android 6). Я также занимался изучением сервисов примерно в 2016, но тестировал этот код на многих девайсах. Как помню, на Android 4.4.2 всегда отрабатывал как ожидается. А вот на более новых версиях + (это жирный плюс, влияющий очень на многое) девайсах разных производителей (очень выделялись на тот момент Xiaomi) дела обстояли очень плохо, т.к. производители вводили свои ограничения для приложений (например, "авто запуск приложения/сервиса" - пользователь должен был разрешить подобное поведение в настройках приложения).
     
    Учитывая свой опыт, могу дать такой совет:
    Попробуйте дать все возможные разрешения на автозапуск приложения/сервиса примерно тут: "Безопасность – Разрешения – Автозапуск – Название вашего приложения" и проверить код ещё раз.
    Вот ещё небольшое описание из моего старого проекта:
     
    Из-за всех этих изменений от производителей, тема стала достаточно непростой. По этой причине считаю, что начинать нужно с нуля, т.е. с официальной справки гугла:
    Службы
    Foreground services
×
×
  • Создать...