-
Постов
326 -
Зарегистрирован
-
Посещение
-
Победитель дней
57
Активность репутации
-
OnePeople получил реакцию от Ingalime в [Android] Воспроизводить аудио
Ну так в 29
public final void startForeground (int id, Notification notification, int foregroundServiceType)
-
OnePeople получил реакцию от Dmitry_4501 в Как получить иконку файла или папки?
Да вроде не должно, тут по идее нужно только расширение файла:
SHGetFileInfo(PChar(Extension),
FILE_ATTRIBUTE_NORMAL,
FileInfo,
SizeOf(FileInfo),
SHGFI_ICON or SHGFI_SMALLICON or
SHGFI_SYSICONINDEX or SHGFI_USEFILEATTRIBUTES
);
-
-
-
-
OnePeople получил реакцию от Ingalime в [Android] Воспроизводить аудио
if TJBuild_VERSION.JavaClass.SDK_INT > 26 then // JBuild_VERSION_CODES.JavaClass.O begin {$ifdef VER330} // new ways for SDK > 26 (won't be called when API < 26 anyways) // Создаем канал уведомления ServiceChannel := TJNotificationChannel.JavaClass.init( StringtoJString('com.radio.one'), //CHANNEL_ID StrToJCharSequence('Public radio Channel'), TJNotificationManager.JavaClass.IMPORTANCE_DEFAULT ); // Получаем указатель на сервис работы с увдомлениями Obj := TAndroidHelper.Context.getSystemService( TJContext.JavaClass.NOTIFICATION_SERVICE); // Выдергиваем оттуда менеджер уведомлений NotificationManager := TJNotificationManager.Wrap(Obj); // Передаем менеджеру наш канал уведомлений NotificationManager.createNotificationChannel(ServiceChannel); // Создаем намерение с параметрами нашего приложения NewIntent:= TAndroidHelper.Context.getPackageManager().getLaunchIntentForPackage( TAndroidHelper.Context.getPackageName()); NewIntent.setAction(TJIntent.JavaClass.ACTION_MAIN); NewIntent.addCategory(TJIntent.JavaClass.CATEGORY_LAUNCHER); NewIntent.addFlags(TJIntent.JavaClass.FLAG_ACTIVITY_NEW_TASK); // Создаем намерение для передачи другому приложению действия с правами нашего приложения PendingIntent := TJPendingIntent.JavaClass.getActivity( TAndroidHelper.Context, 0, NewIntent, TJIntent.JavaClass.FLAG_ACTIVITY_NEW_TASK ); // Создаем уведомление ncb := TJNotificationCompat_Builder.JavaClass.init( TAndroidHelper.Context, StringToJString('com.radio.one') ); // Указываем параметры уведомления // Заголовок уведомления ncb.setContentTitle(StrToJCharSequence('PublicRadio')); // Текст для служб специальных возможностей // Начиная с выпуска L, этот текст больше не отображается на экране, но он по-прежнему полезен для служб специальных возможностей (где он служит звуковым объявлением о появлении уведомления). // ncb.setTicker(StrToJCharSequence('MyCommsService')); // can't remember why this is commented out to be honest // Иконка уведомления ncb.setSmallIcon(JavaService.getApplicationInfo.icon); // Действие при нажатии на уведомления ncb.setContentIntent(PendingIntent); // Действие при нажатии на уведомления // Установите, является ли это "текущим" уведомлением. Текущие уведомления не могут быть отклонены пользователем, поэтому ваше приложение или служба должны позаботиться об их отмене. Они обычно используются для обозначения фоновой задачи, которой пользователь активно занят (например, воспроизведение музыки) или которая каким-то образом ожидает выполнения и поэтому занимает устройство (например, загрузка файла, операция синхронизации, активное сетевое подключение). ncb.setOngoing(True); // Выводим уведомление ntf := ncb.build; Как то так
-
OnePeople получил реакцию от Ingalime в [Android] Воспроизводить аудио
Ну так вы смотрите сразу справку гуугл
CHANNEL_ID -
The id of the channel. Must be unique per package. The value may be truncated if it is too long.
Идентификатор канала. Должно быть уникальным для каждого пакета. Значение может быть усечено, если оно слишком длинное.
Допустим пусть это будет имя пакета + '_id_1'
Смысл в том что приложение может создать несколько уведомлений, и что если вам нужно удалить уведомление вы
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); // The id of the channel. String id = имя пакета + '_id_1'; notificationManager.deleteNotificationChannel(id); -
OnePeople получил реакцию от Ingalime в [Android] Воспроизводить аудио
Тут немного занялся радио у себя, не забудьте добавить ещё эти файлы http://www.un4seen.com/stuff/bass_ssl-android.zip иначе ссылки начинающие с https могут не играть)
-
OnePeople получил реакцию от Ingalime в Android Services
И нужно внимательно читать справку гууууугл
-
OnePeople получил реакцию от Ingalime в 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;
-
OnePeople получил реакцию от Andrey Efimov в 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;
-
OnePeople получил реакцию от Andrey Efimov в Android Services
И нужно внимательно читать справку гууууугл
-
OnePeople получил реакцию от Ingalime в Возможность реализации экспорта/импорта данных приложения в виде файлов
Можете посмотреть какие файлы там есть:
var files: TStringDynArray;
files := TDirectory.GetFiles(TPath.GetHomePath);
TArray.Sort<string>(files, TComparer<string>.Construct(CompareLowerStr));
for i := 0 to Length( files) - 1 do
begin
Memo1.lines.add(files);
end;
-
OnePeople получил реакцию от Yarpda в Возможность реализации экспорта/импорта данных приложения в виде файлов
assets\internal - TPath.GetHomePath
Именно так, только всё это делать вы должны из вашего приложения, так как только оно имеет доступ к этой папке!
-
OnePeople получил реакцию от Ingalime в Возможность реализации экспорта/импорта данных приложения в виде файлов
Ну приложение имеет доступ к этой папке и может делать что хочешь с этим файлом, но только твое приложение, все легко реализуется!
-
OnePeople получил реакцию от Ingalime в [Android] Воспроизводить аудио
С радостью бы помог, и скорее всего если не сможете сделать то помогу, но только ближе к ноябрю(((
Только закончил с поисками и реализацией отловки AudioFocus, наконец то)))))))))
У самого музыка пока не в сервисе, но я думаю как то так, без
AndroidServiceUnBind
function TCronysDM.AndroidServiceStartCommand(const Sender: TObject;
const Intent: JIntent; Flags, StartId: Integer): Integer;
Var
Action: string;
begin
Action := JStringToString(Intent.getAction);
if Action = 'StartService' then
begin
BASS_Init(-1, 44100, 0, nil, nil); //инициализация bass BASS_StreamFree(str); str := BASS_StreamCreateURL(PChar('http://91.199.194.34:8000'), 0, BASS_UNICODE, nil, nil); //ShowMessage(IntToStr(BASS_ErrorGetCode)); If BASS_ErrorGetCode = 0 Then Begin BASS_ChannelPlay(str, True); //начать воспроизведение End; end;
if Action = 'StopService' then
begin
BASS_ChannelStop(str); //остановить воспроизведение BASS_StreamFree(str); JavaService.stopSelf;
result := TJService.JavaClass.START_NOT_STICKY; // don't reload service
exit;
end;
result := TJService.JavaClass.START_STICKY; // rerun service if host app stops
end;
запуск сервиса
FService := TJIntent.Create;
FService.setClassName(TAndroidHelper.Context.getPackageName(),
TAndroidHelper.StringToJString('com.embarcadero.services.cronysrv'));
FService.setAction(StringToJString('StartService'));
TAndroidHelper.Activity.startService(FService);
По вышему коду при убийстве приложения, убивается и сервис???? Это вопрос
-
OnePeople получил реакцию от Ingalime в [Android] Воспроизводить аудио
Создайте сервис в нем код из вашего приложения по запуску воспроизведения
А в приложении, делайте отправку broadcast сообщений о старте или остановки проигрывания
В этом радио так и сделано!
И нотификейшен с кнопками тоже можно на делфи сделать!
-
OnePeople отреагировална krapotkin в Свой APK updater. Использование Fileprovider
У меня в работе два приложения, и оба они не предназначены для Play market, так как имеют ограниченный круг использования, по сути, чисто внутрикорпоративные. Так что нежелательно и выкладывание их и на альтернативные магазины приложений.
Автоматически возникает вопрос обновления. Если в первый раз мы можем установить приложение сами при помощи админов, то обновлять их не так просто. А контингент пользователей не справится с "скачайте APK по ссылке, найдите, куда его скачал браузер, и запустите вручную именно последний скачанный, а не какой попало"...
Простейший способ - дать приложению скачать свежую копию с сайта и натравить на полученный файл системный инсталлер.
Вот только свежие Andoird делать это напрямик запрещают. Нужен filepropvider. Целый день шуровал по мануалам и YT,
Вот то что получилось в результате.
Если у вас 10.3.3 как у меня, уже можно не вносить <provider>...</provider> в манифест и свой файл file_paths.xml (или как вам его советуют назвать в интернетах) в деплой.
Теперь все это делается хоть несколько странно и однобоко, но автоматически, путем установки галочки Secure File Sharing
после этого в манифесте автоматически пропишется один из вариантов размещения файлов, которые вы можете найти в интернете. Используется алиас external-path
файл, показанный на рисунке, создается автоматически самой делфи.
теперь остается отгадать, какой путь реально подставится вместо "."
Как показала практика, все пути выглядят не так, как кажется, если исходить из простого здравого смысла. Целый день использования GetHomeDir и других полезных методов TPath завел меня совсем в тупик.
Оказалось все проще (?)
st:TMemoryStream; OutputDir: JFile; ApkFile: JFile; ApkUri: Jnet_Uri; path, filename: string; ... OutputDir := TAndroidHelper.Context.getExternalCacheDir(); path := JStringToString(OutputDir.getAbsolutePath); filename := path+'/ASDroid2.apk'; ApkFile := TJfile.JavaClass.init( StringToJstring(filename)); FApkUri := TAndroidHelper.JFileToJURI(ApkFile); st.Position := 0; st.SaveToFile(filename); обратите внимание, в provider_paths мы задаем external-paths, а в коде ищем ExternalCacheDir.!!! (For.Unbelievably.Creative.Knowers!)
Потом все просто. FApkUri передаем в интент и запускаем
итоговый код примерно таков. (скачивание в потоке с использованием небольшого собственного API, но там ничего важного, можно не обращать внимания)
procedure TasdSettingsFrame.bDownloadClick(Sender: TObject); begin {$IFDEF ANDROID} bDownload.Enabled := False; DownloadAndRun(); {$ENDIF} end; {$IFDEF ANDROID} procedure TasdSettingsFrame.DownloadAndRun(); begin ttask.Run(procedure var aapi:TasdAPI; st:TMemoryStream; OutputDir: JFile; ApkFile: JFile; ApkUri: Jnet_Uri; path, filename: string; begin st := TMemoryStream.Create; aapi := TasdAPI.Clone(_API); try aapi.OnReceiveData := OnReceiveData; aapi.getApk(st); if aapi.Err.Code=0 then begin OutputDir := TAndroidHelper.Context.getExternalCacheDir(); path := JStringToString(OutputDir.getAbsolutePath); filename := path+'/ASDroid2.apk'; ApkFile := TJfile.JavaClass.init( StringToJstring(filename)); FApkUri := TAndroidHelper.JFileToJURI(ApkFile); st.Position := 0; st.SaveToFile(filename); TThread.Synchronize(nil,procedure begin bDownload.Enabled := true; StartActivity(FApkUri); end); end; finally st.Free; aapi.Free; end; end); end; procedure StartActivity(ApkUri: Jnet_Uri); var Intent: JIntent; begin Intent := TJIntent.Create(); Intent.setAction(TJIntent.JavaClass.ACTION_VIEW); Intent.addFlags(TJIntent.JavaClass.FLAG_ACTIVITY_NEW_TASK or TJIntent.JavaClass.FLAG_ACTIVITY_CLEAR_TOP or TJIntent.JavaClass.FLAG_GRANT_WRITE_URI_PERMISSION or TJIntent.JavaClass.FLAG_GRANT_READ_URI_PERMISSION); Intent.setDataAndType(apkuri, StringToJString('application/vnd.android.package-archive')); TAndroidHelper.Activity.startActivity(Intent); end; procedure TasdSettingsFrame.OnReceiveData(const Sender: TObject; AContentLength: Int64; AReadCount: Int64; var Abort: Boolean); begin tthread.Synchronize(nil, procedure begin pb1.Max := AContentLength; pb1.Value := AReadCount; end); end; {$ENDIF} Вопросы остались конечно, почему так странно с каталогами, но выяснять пока нет желания. Работает - не трожь.
Всем удачи.
UPD.
Для того, чтобы системный инсталлер запускался, нужно не забыть отметить еще одну галочку
-
OnePeople получил реакцию от Ingalime в Программное одноразовое применение InnerGlowEffect к изображению
Поздно, но может кому пригодится
function TForm1.Blur(sbit: TBitmap): TBitmap; var FilterClass: TFilterClass; FFilter: TFilter; FFilterParams: TFilterRec; BitmSource, BitmDest: TBitmap; begin BitmSource:=TBitmap.Create; BitmSource.Assign(sbit); Result:=TBitmap.Create; FFilter := TFilterManager.FilterByName('GaussianBlur'); FilterClass := TFilterManager.FilterClassByName('GaussianBlur'); FFilterParams := FilterClass.FilterAttr; FFilter.ValuesAsFloat['BlurAmount']:=5.7; FFilter.Apply; FFilter.ValuesAsBitmap['Input'] := BitmSource; Result.Assign(FFilter.ValuesAsBitmap['output']); FreeAndNil(FFilter); FreeAndNil(BitmSource); end; function TForm1.Tint(sbit: TBitmap; tintColor: TAlphaColor): TBitmap; var FilterClass: TFilterClass; FFilter: TFilter; FFilterParams: TFilterRec; BitmSource, BitmDest: TBitmap; begin BitmSource:=TBitmap.Create; BitmSource.Assign(sbit); Result:=TBitmap.Create; FFilter := TFilterManager.FilterByName('FillRGB'); FilterClass := TFilterManager.FilterClassByName('FillRGB'); FFilterParams := FilterClass.FilterAttr; FFilter.ValuesAsColor['Color']:=tintColor; FFilter.Apply; FFilter.ValuesAsBitmap['Input'] := BitmSource; Result.Assign(FFilter.ValuesAsBitmap['output']); FreeAndNil(FFilter); FreeAndNil(BitmSource); end;
-
OnePeople получил реакцию от Tumaso в Программное одноразовое применение InnerGlowEffect к изображению
Поздно, но может кому пригодится
function TForm1.Blur(sbit: TBitmap): TBitmap; var FilterClass: TFilterClass; FFilter: TFilter; FFilterParams: TFilterRec; BitmSource, BitmDest: TBitmap; begin BitmSource:=TBitmap.Create; BitmSource.Assign(sbit); Result:=TBitmap.Create; FFilter := TFilterManager.FilterByName('GaussianBlur'); FilterClass := TFilterManager.FilterClassByName('GaussianBlur'); FFilterParams := FilterClass.FilterAttr; FFilter.ValuesAsFloat['BlurAmount']:=5.7; FFilter.Apply; FFilter.ValuesAsBitmap['Input'] := BitmSource; Result.Assign(FFilter.ValuesAsBitmap['output']); FreeAndNil(FFilter); FreeAndNil(BitmSource); end; function TForm1.Tint(sbit: TBitmap; tintColor: TAlphaColor): TBitmap; var FilterClass: TFilterClass; FFilter: TFilter; FFilterParams: TFilterRec; BitmSource, BitmDest: TBitmap; begin BitmSource:=TBitmap.Create; BitmSource.Assign(sbit); Result:=TBitmap.Create; FFilter := TFilterManager.FilterByName('FillRGB'); FilterClass := TFilterManager.FilterClassByName('FillRGB'); FFilterParams := FilterClass.FilterAttr; FFilter.ValuesAsColor['Color']:=tintColor; FFilter.Apply; FFilter.ValuesAsBitmap['Input'] := BitmSource; Result.Assign(FFilter.ValuesAsBitmap['output']); FreeAndNil(FFilter); FreeAndNil(BitmSource); end;
-
OnePeople получил реакцию от Ingalime в [Android] Воспроизводить аудио
Пользуюсь этим pas попробуйте
bassandr.rar
-
OnePeople получил реакцию от Ingalime в Посоветуйте компонет
Если платформа Android:
1. listbox тормознутый вариант, но да ооочень простой и удобный
2. Alcinoe - набор примитивов которым можно программно сделать любой список, скорость отрисовки бомбическая, косяк в том что создаются компоненты долговато, нужна грамотная реализация подрузки данных и создания компонентов, но по мне это лучший вариант для горизонтального списка.
3. ListView если список вертикальный то самое оно для вас, единственное с выравниванием и динамической высотой поработать нужно будет, но код есть в сети.
-
OnePeople получил реакцию от Ingalime в NotificationListenerService
Вот статья с инструкцией, по созданию сервиса
https://stackoverflow.com/questions/27962192/is-it-possible-to-read-the-notifications-of-other-applications-on-android-with-d
Единственное я удалил с исходника сервиса, все что связанно с
import android.support.v4.content.LocalBroadcastManager; и использовал обычный BroadcastReciver
Далее даем разрешение
BIND NOTIFICATION LISTENER SERVICE
В манифесте после строки <%services%> дописываем
<service android:name="com.embarcadero.ИМЯ ВАШЕГО СЕРВИСА.NotificationService" android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE"> <intent-filter> <action android:name="android.service.notification.NotificationListenerService" /> </intent-filter> </service> Иконку доставать так
iconapp:=TBitmap.Create; Surface := TBitmapSurface.Create; NotifyDraw:=TAndroidHelper.Context.createPackageContext(stpackage, 0).getResources.getDrawableForDensity(idicon, 480); if StrToInt(NotifyDraw.getAlpha.ToString)=255 then Bitmap := TJBitmapDrawable.Wrap((NotifyDraw.getCurrent as ILocalObject).GetObjectID).getBitmap; if Bitmap<>nil then begin JBitmapToSurface(Bitmap, Surface); iconapp.Assign(Surface); end;
-
OnePeople получил реакцию от Дмитрий Куксов в NotificationListenerService
Вот статья с инструкцией, по созданию сервиса
https://stackoverflow.com/questions/27962192/is-it-possible-to-read-the-notifications-of-other-applications-on-android-with-d
Единственное я удалил с исходника сервиса, все что связанно с
import android.support.v4.content.LocalBroadcastManager; и использовал обычный BroadcastReciver
Далее даем разрешение
BIND NOTIFICATION LISTENER SERVICE
В манифесте после строки <%services%> дописываем
<service android:name="com.embarcadero.ИМЯ ВАШЕГО СЕРВИСА.NotificationService" android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE"> <intent-filter> <action android:name="android.service.notification.NotificationListenerService" /> </intent-filter> </service> Иконку доставать так
iconapp:=TBitmap.Create; Surface := TBitmapSurface.Create; NotifyDraw:=TAndroidHelper.Context.createPackageContext(stpackage, 0).getResources.getDrawableForDensity(idicon, 480); if StrToInt(NotifyDraw.getAlpha.ToString)=255 then Bitmap := TJBitmapDrawable.Wrap((NotifyDraw.getCurrent as ILocalObject).GetObjectID).getBitmap; if Bitmap<>nil then begin JBitmapToSurface(Bitmap, Surface); iconapp.Assign(Surface); end;
-
OnePeople получил реакцию от Евгений Корепов в TListView DynamicAppearance ItemAppearanceObjects.ItemObjects.ObjectsCollection
procedure TForm1.ListViewUpdateObjects(const Sender: TObject;
const AItem: TListViewItem);
begin
TListItemText(AItem.Objects.FindDrawable('Detail')).Width:=Ваша ширина;
end;