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

TNotificationCenter. Можно ли изменить иконку?


Alex Bozhko

Вопрос

Собствено, сабж. Можно ли изменить пиктограмму для нотификатора вообще и в Андроид в частности? По умолчанию,  показывается иконка приложения, а мне надо показывать несколько разных иконок.

 

Спасибо.

Ссылка на комментарий

Рекомендуемые сообщения

  • 0
  • Модераторы

Пока вижу только такой вариант: Нужно лезть в исходники и там менять, конкретно вот здесь "FMX.Notification.Android.pas", предположительно 132 и 137 строчки.

Ссылка на комментарий
  • 0
В 02.09.2016 в 09:59, Pax Beach сказал:

Коллеги, есть ли успехи в решении этого вопроса?

Поделитесь опытом плиз.

Чтобы не лезть в исходники, можно сделать так для Android:

1. В Deployment : добавляешь нужную картинку X.png и устанавливаешь у картинки "Remote Path" "res\drawable\";

2. В коде перед созданием уведомления добавляешь:

const
    IMAGE = 'drawable/X'; //расширение картинки не указывается
var
    lId : Integer;
begin
    lId := TAndroidHelper.Context.getResources().getIdentifier(
        StringToJString(IMAGE),
        StringToJString('drawable'),
        TAndroidHelper.Context.getPackageName);
    TAndroidHelper.Context.getApplicationInfo.icon := lId; //именно отсюда потом берется Id картинки для локального уведомления

*Проверял на Android 4.4, в более поздних версиях могут быть различия, версия IDE =  Delphi 10 Seattle.

**В прошивках типа MIUI код выше может не работать из-за жестокого кеширования.

Ссылка на комментарий
  • 0
2 часа назад, Fedor K сказал:

Чтобы не лезть в исходники, можно сделать так для Android:

1. В Deployment : добавляешь нужную картинку X.png и устанавливаешь у картинки "Remote Path" "res\drawable\";

2. В коде перед созданием уведомления добавляешь:

По поводу кэширования ресурсов, наверняка есть метод, который этим делом управляет, не разбирался пока.

В приведенном примере иконка изменится у всего приложения везде?

Ссылка на комментарий
  • 1

Иконка изменится внутри приложения в рамах текущего контекста до ее завершения. С других приложений и в системе ничего не поменяется (см. прикрепление).

Чтобы не влиять на другой функционал, достаточно сделать следующее:

    //запоминаем ид по умолчанию
    lDefaultId := TAndroidHelper.Context.getApplicationInfo.icon;
    //устанавливаем нашу кастомную иконку
    TAndroidHelper.Context.getApplicationInfo.icon := lId;
    //создаем локальное уведомление
    NotificationCenter.PresentNotification(lNotification);
    //возвращаем обратно
    TAndroidHelper.Context.getApplicationInfo.icon := lDefaultId;

п.с. Если такой вариант не устраивает, всегда можно написать class helper for TBaseNotificationCenter и использовать классы JNotificationCompat_Builder, JNotificationManager, JNotification. Справка из developer.android.com.

Test.png

Ссылка на комментарий
  • 0

Fedor K, Ваш вариант у меня не получается реализовать :(

У меня host-приложение со службой.

В приложении, в deployment, добавил 2 png файла, дал им имена в колонке remote name. Сделал deploy проекта.

В папке "\Android\Debug\имя_пакета\res\drawable" появились нужные файлы.

При создании службы выполняю
 

procedure TDMSrv.SetIDIconMed;
const
 img_is_med = 'drawable/med';
 img_not_med = 'drawable/nomed';
begin
//значок 1
  iIDIconMedY := TAndroidHelper.Context.getResources.getIdentifier(
                   StringToJString(img_is_med),
                   StringToJString('drawable'),
                   StringToJString('имя.пакета.host-приложения'));

// значок 2
  iIDIconMedN := TAndroidHelper.Context.getResources.getIdentifier(
                   StringToJString(img_not_med),
                   StringToJString('drawable'),
                   StringToJString('имя.пакета.host-приложения'));

end;

 

 

При оповещении:

procedure TDMSrv.LaunchNotification(const sTel, sTypeCall: string; idIconMed: integer);
begin
...
...
...
    //запоминаем значок приложения по умолчанию
    lDefaultId := TAndroidHelper.Context.getApplicationInfo.icon;

    //устанавливаем значок в зависимости от того, посредник или нет
    TAndroidHelper.Context.getApplicationInfo.icon := idIconMed;

    //показываем оповещение
    MyNotification.FireDate := IncSecond(Now, 1);
    NotificationCenter1.ScheduleNotification(MyNotification);

    //возвращаем значок приложения обратно
    TAndroidHelper.Context.getApplicationInfo.icon := lDefaultId;

    MyNotification.DisposeOf
end;

 

Вызываю, передавая нужный ID
 

LaunchNotification('...', '...', iIDIconMedY);

или

LaunchNotification('...', '...', iIDIconMedN);

 

Но всплывает при оповещении всё равно стандартный значок приложения.

 

Delphi Tokyo.

Screenshot_1.png

Изменено пользователем x11
Ссылка на комментарий
  • 0
17 часов назад, x11 сказал:

img_is_med = 'drawable/med'; img_not_med = 'drawable/nomed';

Первый ресурс (ismed) - будет 0, т.е. его нет, потому как в деплое он обозначен как ismed.png. Второй ресурс нашелся.

На мой взгляд, лучше скопируйте себе System.Android.Notification, и внесите правки в него. Функция CreateNativeNotification (в Берлине 125 строка). Там можете и картинки назначать, и кнопку создать, и прогресс, и хронометр тот же вывести, в общем, процесс для творчества будет безграничен.

Так же и к предыдущей теме вашей пригодится - тот же .startForeground для сервиса, ну или "несмахиваемое" уведомление (.setOngoing(True))

Ссылка на комментарий
  • 0

Ок.

Как вариант, что можно придумать, чтобы показать из службы что-то вроде Toast, но чтобы это небольшое окошко/надпись была на экране значительно дольше + вставить туда кроме надпись, ещё и значок.

Задача простая. При звонке показать, что номер телефона имеет такой-то признак. Чтобы пользователь смартфона видел это при вход./исход. звонке.

Ссылка на комментарий
  • 0

Может кому пригодится пример с использованием startForeground, а то в справке по Delphi не нашёл

uses System.Android.Notification, AndroidApi.JNI.Support; // для JNotification и JNotificationCompat_Builder
...
...
function TDMSrv.AndroidServiceStartCommand(const Sender: TObject; const Intent: JIntent; Flags, StartId: Integer): Integer;
Var
  Action: string;
  notification: JNotification;
  NotificationBuilder: JNotificationCompat_Builder;
begin
  Action := JStringToString(Intent.getAction);

//  if Action = 'StartService' then
//    CreateBroadcastReceiver;

  if Action = 'StopService' then
  begin
    JavaService.stopSelf;
    result := TJService.JavaClass.START_NOT_STICKY; // don't reload service
    Log('Service stoped');
    exit;
  end;

    NotificationBuilder := TJNotificationCompat_Builder.JavaClass.init(TAndroidHelper.Context);
    NotificationBuilder := NotificationBuilder.setSmallIcon(TAndroidHelper.Context.getApplicationInfo.icon);
    NotificationBuilder := NotificationBuilder.setContentTitle(StrToJCharSequence(TAndroidHelper.ApplicationTitle));
    NotificationBuilder := NotificationBuilder.setContentText(StrToJCharSequence('тело сообщения'));
    notification := NotificationBuilder.build;


  Self.JavaService.startForeground(1, notification);

  result := TJService.JavaClass.START_STICKY; // rerun service if host app stops
end;

Не нашёл информации, почему именно 1 здесь:

Self.JavaService.startForeground(1, notification);

 

Это в  DataModule, который в службе

TDMSrv = class(TAndroidService)

Изменено пользователем x11
Ссылка на комментарий
  • 0
2 часа назад, x11 сказал:

Может кому пригодится пример с использованием startForeground, а то в справке по Delphi не нашёл

При работе с API конкретной платформы советую использовать именно справку самой платформы. Находим реализацию на родном языке и пытаемся повторить тоже самое через wrappers от Delphi.

2 часа назад, x11 сказал:

Не нашёл информации, почему именно 1 здесь:

Self.JavaService.startForeground(1, notification);

1 - это идентификатор вашего сервиса отличный от 0 (см. подробнее Service | Android Developers), т.е. можете использовать любые положительные цифры. По сути и обычные уведомления тоже содержат такой идентификатор, но это практически редко используется.

Ссылка на комментарий
  • 0
7 часов назад, Fedor K сказал:

Находим реализацию на родном языке и пытаемся повторить тоже самое через wrappers от Delphi.

к сожалению примеров, информации и справки очень мало, а сообщество FMX всё ещё не очень большое

Ссылка на комментарий
  • 0

Не надо использовать START_STICKY если экшен в интенте был не пустой, т.к. при выгрузке службы и повторной попытке ее запуска системой (мы ж отметили что служба очень важная), придет пустой экшен.

Стартуйте с START_REDELIVER_INTENT, что бы система отправила тот же интент, с которым служба запускалась до выгрузки.

Цитата

к сожалению примеров, информации и справки очень мало, а сообщество FMX всё ещё не очень большое

Ну наверное в справке к FMX и не должно расписываться взаимодействие со всеми API целевых платформ. В качестве примера и для понимания принципов, как работать с ними, можно просто открыть исходники и сопоставить с доками того же гугла

Ссылка на комментарий
  • 0

Разницы между START_STICKY  и START_REDELIVER_INTENT для меня нет.

Мне главное, чтобы при (пере)создании службы, был создан и BroadcastReceiver,который будет ждать вызова.
 

procedure TDMSrv.AndroidServiceCreate(Sender: TObject);
begin
  CreateBroadcastReceiver;
end;

procedure TDMSrv.CreateBroadcastReceiver;
begin
  if not assigned(fBroadcastReceiver) then
  begin
    fBroadcastReceiver := TCSBroadcastReceiver.Create(nil);
    Log('not assigned BroadcastReceiver, creating: ' + fBroadcastReceiver.ToString);
  end;

  fBroadcastReceiver.OnReceive := BroadcastReceiverOnReceive;
  fBroadcastReceiver.Clear;// Items.Clear;

  fBroadcastReceiver.RegisterReceiver;
  fBroadcastReceiver.Add(PHONE_STATE);
  fBroadcastReceiver.Add(NEW_OUTGOING_CALL);

  Log('CreateBroadcastReceiver');
end;

 

Ссылка на комментарий

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить на вопрос...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу
×
×
  • Создать...