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

Использование нативных LocalBroadcastManager и BroadcastReceiver


Pax Beach

Вопрос

Из PlatformSDK (PlatformSDKs\android-sdk-windows\sources\android-23\android\support\v4\content\) портировал в Delphi класс TJLocalBroadcastManager.

Это очень полезный класс, если вы не хотите рассылать сообщения по всей системе, а есть необходимость общаться только внутри приложения или между хост-приложением и сервисом.

Во вложении сам класс, в своем приложении убедитесь, что в Target Platforms (Android) → Android → Libraries включена библиотека android-support-v4.dex.jar.

 

Прилагаю пример, для изучения и использования в работе, который демонстрирует работу обычного BroadcastReceiver и LocalBroadcastReceiver.

В примере демонстрируется работа сообщений в приложении и сервисе. Сначала делаем build проекта LBCRService, потом будет доступна возможность собрать LocalBCR.

Собираю в Berlin 10.1, но на младших версиях тоже должно работать, по крайней мере в Seatlle.

 

В реализации методов

    procedure RegisterReceiver();
    procedure UnRegisterReceiver();

необходимо снять комментарий с соответствующих строчек, в зависимости от того, какой тип ресивера вы хотите использовать.

 

 

Androidapi.JNI.LocalBroadcastManager.pas.zip

LocalBroadCastReceiver.zip

Изменено пользователем Pax Beach
дополнил решение
Ссылка на комментарий

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

  • 0
7 минут назад, ZuBy сказал:

ну что я могу сказать, все висит. ничего не могу сделать

android 6.0.1

Где висит?

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

Исходный код открыт, можно понять, где зависает.

 

Изменено пользователем Pax Beach
Ссылка на комментарий
  • 0
14 минуты назад, ZuBy сказал:

приложение запускается и всё, ничего нажать невозможно

Как видно в исходных кодах, при создании, запуске или активации контролов нет ни каких обработчиков. События начинаются, когда жмете на кнопки.

Монитор что-нибудь полезное сообщает?

Я тестирую на платформе android-19, SDK 23.0.3. Что у Вас стоит?

 

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

При входящем звонке система сама рассылает уведомление об этом. Нужно на него просто подписаться. Код уведомления надо поискать в справочнике разработчика.

Предполагаю, что здесь https://developer.android.com/reference/android/telephony/TelephonyManager.html

 

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

Я предлагаю использовать вызовы методов этого интерфейса. Уже все написано за вас.

Не зная, как пользоваться Android Developer, под Android не получится ничего толкового написать.

Ссылка на комментарий
  • 0
3 часа назад, Pax Beach сказал:

Не зная, как пользоваться Android Developer, под Android не получится ничего толкового написать.

Так в том-то и дело, что те, кто знает Java и Android, не будут использовать FMX.

 

 

3 часа назад, Pax Beach сказал:

Я предлагаю использовать вызовы методов этого интерфейса. Уже все написано за вас.

Я, например, пока что не имею представления о том, как использовать методы этого интерфейса.

Ссылка на комментарий
  • 0
В 04.07.2016 в 12:44, Pax Beach сказал:

LocalBroadCastReceiver.zip

проект не компилируется в Tokyo

 

Цитата

[Exec Error] The command "PATH  ... ... ... exited with code 1.

 

Наверное из-за этого.

Screenshot_1.png

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

Взял Ваш пример. Убрал всё лишнее. Вернее оставил приём сообщений только в службе.

Добавил разрешение process outgouin calls. Добавил в AndroidManifest.template.xml receiver.

Скомпилировал, запустил.

Когда нажимаю кнопку отправки сообщения в самом приложении, то в логе видно, что сообщение приходит в сервис.

Но когда выполняю физически исходящий звонок на Андроиде, то приложение валится с кучей ошибок:

Скрытый текст

01-23 20:48:02.348: I/info(18974): Sended the action ACTION_NEW_OUTGOING_CALL
01-23 20:48:02.358: I/info(18974): SVC TMyReceiverListener.onReceive: ACTION_NEW_OUTGOING_CALL
01-23 20:48:09.256: E/AndroidRuntime(18974): FATAL EXCEPTION: main
01-23 20:48:09.256: E/AndroidRuntime(18974): Process: com.embarcadero.LocalBCR, PID: 18974
01-23 20:48:09.256: E/AndroidRuntime(18974): java.lang.RuntimeException: Unable to instantiate receiver com.embarcadero.LocalBCR.OutgoingCallReceiver: java.lang.ClassNotFoundException: Didn't find class "com.embarcadero.LocalBCR.OutgoingCallReceiver" on path: DexPathList[[zip file "/data/app/com.embarcadero.LocalBCR-1/base.apk"],nativeLibraryDirectories=[/data/app/com.embarcadero.LocalBCR-1/lib/arm, /vendor/lib, /system/lib]]
01-23 20:48:09.256: E/AndroidRuntime(18974):     at android.app.ActivityThread.handleReceiver(ActivityThread.java:2689)
01-23 20:48:09.256: E/AndroidRuntime(18974):     at android.app.ActivityThread.access$1700(ActivityThread.java:144)
01-23 20:48:09.256: E/AndroidRuntime(18974):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1449)
01-23 20:48:09.256: E/AndroidRuntime(18974):     at android.os.Handler.dispatchMessage(Handler.java:102)
01-23 20:48:09.256: E/AndroidRuntime(18974):     at android.os.Looper.loop(Looper.java:155)
01-23 20:48:09.256: E/AndroidRuntime(18974):     at android.app.ActivityThread.main(ActivityThread.java:5727)
01-23 20:48:09.256: E/AndroidRuntime(18974):     at java.lang.reflect.Method.invoke(Native Method)
01-23 20:48:09.256: E/AndroidRuntime(18974):     at java.lang.reflect.Method.invoke(Method.java:372)
01-23 20:48:09.256: E/AndroidRuntime(18974):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1029)
01-23 20:48:09.256: E/AndroidRuntime(18974):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:824)
01-23 20:48:09.256: E/AndroidRuntime(18974): Caused by: java.lang.ClassNotFoundException: Didn't find class "com.embarcadero.LocalBCR.OutgoingCallReceiver" on path: DexPathList[[zip file "/data/app/com.embarcadero.LocalBCR-1/base.apk"],nativeLibraryDirectories=[/data/app/com.embarcadero.LocalBCR-1/lib/arm, /vendor/lib, /system/lib]]
01-23 20:48:09.256: E/AndroidRuntime(18974):     at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56)
01-23 20:48:09.256: E/AndroidRuntime(18974):     at java.lang.ClassLoader.loadClass(ClassLoader.java:511)
01-23 20:48:09.256: E/AndroidRuntime(18974):     at java.lang.ClassLoader.loadClass(ClassLoader.java:469)
01-23 20:48:09.256: E/AndroidRuntime(18974):     at android.app.ActivityThread.handleReceiver(ActivityThread.java:2684)
01-23 20:48:09.256: E/AndroidRuntime(18974):     ... 9 more
01-23 20:48:09.256: E/AndroidRuntime(18974):     Suppressed: java.lang.ClassNotFoundException: com.embarcadero.LocalBCR.OutgoingCallReceiver
01-23 20:48:09.256: E/AndroidRuntime(18974):         at java.lang.Class.classForName(Native Method)
01-23 20:48:09.256: E/AndroidRuntime(18974):         at java.lang.BootClassLoader.findClass(ClassLoader.java:781)
01-23 20:48:09.256: E/AndroidRuntime(18974):         at java.lang.BootClassLoader.loadClass(ClassLoader.java:841)
01-23 20:48:09.256: E/AndroidRuntime(18974):         at java.lang.ClassLoader.loadClass(ClassLoader.java:504)
01-23 20:48:09.256: E/AndroidRuntime(18974):         ... 11 more
01-23 20:48:09.256: E/AndroidRuntime(18974):     Caused by: java.lang.NoClassDefFoundError: Class not found using the boot class loader; no stack available
01-23 20:48:11.198: D/Process(18974): killProcess, pid=18974
01-23 20:48:11.208: D/Process(18974): com.android.internal.os.RuntimeInit$UncaughtHandler.uncaughtException:138 java.lang.ThreadGroup.uncaughtException:693 java.lang.ThreadGroup.uncaughtException:690
01-23 20:48:11.488: E/Typeface(19911): SANS_LOC file not found.
01-23 20:48:11.498: E/AndroidRuntime(19911): FATAL EXCEPTION: main
01-23 20:48:11.498: E/AndroidRuntime(19911): Process: com.embarcadero.LocalBCR, PID: 19911
01-23 20:48:11.498: E/AndroidRuntime(19911): java.lang.RuntimeException: Unable to instantiate receiver com.embarcadero.LocalBCR.OutgoingCallReceiver: java.lang.ClassNotFoundException: Didn't find class "com.embarcadero.LocalBCR.OutgoingCallReceiver" on path: DexPathList[[zip file "/data/app/com.embarcadero.LocalBCR-1/base.apk"],nativeLibraryDirectories=[/data/app/com.embarcadero.LocalBCR-1/lib/arm, /vendor/lib, /system/lib]]
01-23 20:48:11.498: E/AndroidRuntime(19911):     at android.app.ActivityThread.handleReceiver(ActivityThread.java:2689)
01-23 20:48:11.498: E/AndroidRuntime(19911):     at android.app.ActivityThread.access$1700(ActivityThread.java:144)
01-23 20:48:11.498: E/AndroidRuntime(19911):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1449)
01-23 20:48:11.498: E/AndroidRuntime(19911):     at android.os.Handler.dispatchMessage(Handler.java:102)
01-23 20:48:11.498: E/AndroidRuntime(19911):     at android.os.Looper.loop(Looper.java:155)
01-23 20:48:11.498: E/AndroidRuntime(19911):     at android.app.ActivityThread.main(ActivityThread.java:5727)
01-23 20:48:11.498: E/AndroidRuntime(19911):     at java.lang.reflect.Method.invoke(Native Method)
01-23 20:48:11.498: E/AndroidRuntime(19911):     at java.lang.reflect.Method.invoke(Method.java:372)
01-23 20:48:11.498: E/AndroidRuntime(19911):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1029)
01-23 20:48:11.498: E/AndroidRuntime(19911):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:824)
01-23 20:48:11.498: E/AndroidRuntime(19911): Caused by: java.lang.ClassNotFoundException: Didn't find class "com.embarcadero.LocalBCR.OutgoingCallReceiver" on path: DexPathList[[zip file "/data/app/com.embarcadero.LocalBCR-1/base.apk"],nativeLibraryDirectories=[/data/app/com.embarcadero.LocalBCR-1/lib/arm, /vendor/lib, /system/lib]]
01-23 20:48:11.498: E/AndroidRuntime(19911):     at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56)
01-23 20:48:11.498: E/AndroidRuntime(19911):     at java.lang.ClassLoader.loadClass(ClassLoader.java:511)
01-23 20:48:11.498: E/AndroidRuntime(19911):     at java.lang.ClassLoader.loadClass(ClassLoader.java:469)
01-23 20:48:11.498: E/AndroidRuntime(19911):     at android.app.ActivityThread.handleReceiver(ActivityThread.java:2684)
01-23 20:48:11.498: E/AndroidRuntime(19911):     ... 9 more
01-23 20:48:11.498: E/AndroidRuntime(19911):     Suppressed: java.lang.ClassNotFoundException: com.embarcadero.LocalBCR.OutgoingCallReceiver
01-23 20:48:11.498: E/AndroidRuntime(19911):         at java.lang.Class.classForName(Native Method)
01-23 20:48:11.498: E/AndroidRuntime(19911):         at java.lang.BootClassLoader.findClass(ClassLoader.java:781)
01-23 20:48:11.498: E/AndroidRuntime(19911):         at java.lang.BootClassLoader.loadClass(ClassLoader.java:841)
01-23 20:48:11.498: E/AndroidRuntime(19911):         at java.lang.ClassLoader.loadClass(ClassLoader.java:504)
01-23 20:48:11.498: E/AndroidRuntime(19911):         ... 11 more
01-23 20:48:11.498: E/AndroidRuntime(19911):     Caused by: java.lang.NoClassDefFoundError: Class not found using the boot class loader; no stack available

 

 

Пока не знаю, куда дальше копать.

Это моя вина? Я что-то забыл? Что-то не так сделал?

 

Я так понимаю, что проблема в этом?

Цитата

Caused by: java.lang.ClassNotFoundException: Didn't find class "com.embarcadero.LocalBCR.OutgoingCallReceiver"

Я что-то неправильно в XML прописал?

Screenshot_1.png

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

Пока я не понял, что прописать в XML


<receiver android:name=".OutgoingCallReceiver" >

вместо ".OutgoingCallReceiver"

Нет Дельфи под рукой, трудно подсказать.
А можно весь манифест увидеть, и monitor log желательно, права в проекте все предоставлены?

Кстати Android какой, а то может права дополнительно Runtime запрашивать надо?

На форуме есть все примеры для этого.

Свой пример писал кажется под Android 5.0.

 

Ссылка на комментарий
  • 0
1 час назад, Pax Beach сказал:


А можно весь манифест увидеть

прикрепил проект

 

1 час назад, Pax Beach сказал:

Свой пример писал кажется под Android 5.0.

я запускал на Android 5.0.2

BR.rar

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

вот кусок кода из сервиса из Вашего примера

else if Action = 'KillApplication' then
  begin
    Log('"Die! command geted');
    Intent.setAction(StringToJString('StartService'));

    TJActivityManager.Wrap((LJO as ILocalObject).GetObjectID)
      .killBackgroundProcesses(StringToJString('com.embarcadero.LocalBCR'));
  end

Подскажите, зачем при "KillApplication" выполнять "StartService"?

Ссылка на комментарий
  • 0
procedure TfmMain.btStopServiceStartCommandClick(Sender: TObject);
begin
  Log('Service to be stoped by StartCommand');
  FService := TJIntent.Create;
  FService.setClassName(TAndroidHelper.Context.getPackageName(),
    TAndroidHelper.StringToJString('com.embarcadero.services.LBCRService'));
  FService.setAction(StringToJString('StopService'));
  TAndroidHelper.Activity.startService(FService);
end;

 

а зачем здесь "startService" последней строкой?

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

procedure TfmMain.btStopServiceStartCommandClick(Sender: TObject);
begin
  Log('Service to be stoped by StartCommand');
  FService := TJIntent.Create;
  FService.setClassName(TAndroidHelper.Context.getPackageName(),
    TAndroidHelper.StringToJString('com.embarcadero.services.LBCRService'));
  FService.setAction(StringToJString('StopService'));
  TAndroidHelper.Activity.startService(FService);
end;

 

а зачем здесь "startService" последней строкой?

StartCommand вызывается каждый раз, когда мы вызываем из приложения StartService.

А как обрабатывать намерение (Intent) переданный в этот метод — это наше дело.

У меня в этой команде обрабатывался и старт и стоп.

Убивать приложение через KillBackgroundProcess не обязательно, это осталось от моего другого приложения, где выгрузить процесс из памяти было критичным.

 

Изменено пользователем Pax Beach
Ссылка на комментарий
  • 0
function TDM.AndroidServiceStartCommand( ...
..
..

  if Action = 'KillApplication' then
  begin
    Log('"Die! command geted');
    Intent.setAction(StringToJString('StartService'));

    TJActivityManager.Wrap(ILocalObject(LJO).GetObjectID).killBackgroundProcesses(StringToJString('com.embarcadero.LocalBCR'));
  end;

А зачем StartService в KillApplication?

Ссылка на комментарий
  • 0
34 минуты назад, x11 сказал:

function TDM.AndroidServiceStartCommand( ...
..
..

  if Action = 'KillApplication' then
  begin
    Log('"Die! command geted');
    Intent.setAction(StringToJString('StartService'));

    TJActivityManager.Wrap(ILocalObject(LJO).GetObjectID).killBackgroundProcesses(StringToJString('com.embarcadero.LocalBCR'));
  end;

А зачем StartService в KillApplication?

А где в вызове killBackgroundProcesses используется этот интент? — нигде.

Поэтому незачем.

Я же говорю — Осталось от предыдущего кода.

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

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

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

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

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

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

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

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

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

×
×
  • Создать...