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

Событие при входящем звонке


Rionn

Вопрос

Добрый день.  Существует задача выполнять некоторые действия если звонит на телефон определенный номер. Как понимаю тут надо использовать android service. Но не могу найти код для этой проверки входящего звонка. И если вставлять, то куда в StartOnCommand на сервисе?

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

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

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

Общие шаги такие: Подписываетесь через BroadcastReceiver на READ_PHONE_STATE (и возможно ещё на что-то) и при звонке проверяете состояние и номер. Если выполнять действия надо скрытно, то пишите сервис

 

p.s. Тему перенёс в подходящий раздел.

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

Ну как, скрытно. Мне же человек может в любой момент позвонить, поэтому, нужно, чтобы это программа работала постоянно. Поэтому скорее всего сервис. Честно говоря с таким сталкиваюсь первый раз, не мог бы кто хотя бы ссылку или кусок кода дать, чтобы начать работать как-то с этим. Потому что у меня основная проблема с определением номера, а остальное я сам знаю впринципе.

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

Ну как, скрытно. Мне же человек может в любой момент позвонить, поэтому, нужно, чтобы это программа работала постоянно. Поэтому скорее всего сервис. Честно говоря с таким сталкиваюсь первый раз, не мог бы кто хотя бы ссылку или кусок кода дать, чтобы начать работать как-то с этим. Потому что у меня основная проблема с определением номера, а остальное я сам знаю впринципе.

Зачем вам постоянно висящий в памяти сервис, если он нужен только когда поступил звонок от определённого номера? Вы читали то, что я написал в первом сообщении (особенно про BroadcastReceiver)?

Сразу говорю, что готовый код на Delphi/С++, с вероятностью 99% - вы не найдёте, только на Java (на стеке например).

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

 

p.s. Я бы сделал так, подписался через BroadcastReceiver на событие, как только событие происходит, проверяю номер и далее уже запускаю сервис, что-то делаю в нём, завершаю работу сервиса. ИЛИ событие происходит, запускаю сервис, в нём проверяю номер и т.д. Тут либо экспериментировать, либо найти готовое решение или описание решения на Java и транслировать на Delphi.

 

Пара ссылок:

[Android Service] Создание простейшего Сервиса (службы)

[BroadcastReceiver] Автозапуск приложения после перезагрузки ОС

[Android Service+BroadcastReceiver] Автозапуск службы после рестарта ОС

 

 

Ссылка на комментарий
  • 1
В 27.11.2016 в 11:32, Rusland сказал:

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

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

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs,
   CSBroadcastReceiver,Androidapi.Jni,
  AndroidApi.JNI.GraphicsContentViewText,
  Androidapi.Jni.JavaTypes,
  Androidapi.JNI.Os,
  Androidapi.JNIBridge,
  Androidapi.JNI.Telephony, FMX.Controls.Presentation, FMX.ScrollBox, FMX.Memo,
  FMX.StdCtrls;

type
  TForm1 = class(TForm)
  private
    { Private declarations }
    procedure CreateBroadcastReceiver;
    procedure CheckPhoneCallState(Context: JContext; Intent: JIntent);
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  BroadcastReceiver: TCSBroadcastReceiver;

implementation

uses
  Androidapi.Jni.App, Androidapi.Helpers, Androidapi.Log,
  FMX.Helpers.Android;

{$R *.fmx}

procedure TForm1.CreateBroadcastReceiver;
begin
  if not Assigned(BroadcastReceiver) then
    begin
      BroadcastReceiver:= TCSBroadcastReceiver.Create(nil);
      //BroadcastReceiver.OnReceive:= BroadcastReceiverOnReceive;
      BroadcastReceiver.RegisterReceive;
      BroadcastReceiver.Add('android.intent.action.PHONE_STATE');
      BroadcastReceiver.Add('android.intent.action.READ_PHONE_STATE');
    end;
end;

procedure TForm1.CheckPhoneCallState(Context: JContext; Intent: JIntent);
var
  telephonyService: JObject;
  telephonyManager: JTelephonyManager;
  state: JString;
  incomingCallNumber: string;
  outputResult: string;
  VibratorObj: JObject;
  Vibrator: JVibrator;
begin
  outputResult:= #13#10;

  telephonyService := TAndroidHelper.Context.getSystemService(TJContext.JavaClass.TELEPHONY_SERVICE);
  telephonyManager := TJTelephonyManager.Wrap((telephonyService as ILocalObject).GetObjectID);

  if JStringToString(Intent.getAction).Equals('android.intent.action.READ_PHONE_STATE') then
  begin
  if incomingCallNumber = 'номер телефона' then
    VibratorObj := SharedActivity.getSystemService(TJActivity.JavaClass.VIBRATOR_SERVICE);
  Vibrator := TJVibrator.Wrap((VibratorObj as ILocalObject).GetObjectID);
  Vibrator.vibrate(10);
  end;

end;

end.

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

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

А с чего у вас будет срабатывать метод

CheckPhoneCallState

если вы его не зарегистрировали как OnReceive

У вас вообще строчка закомментирована

//BroadcastReceiver.OnReceive:= BroadcastReceiverOnReceive;

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

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

 

Дополнение:

А что за компонент вы используете? там при каждом Add перерегистрация происходит? Обычно регистрация в таком порядке происходит:

      BroadcastReceiver:= TCSBroadcastReceiver.Create(nil);
      BroadcastReceiver.OnReceive:= BroadcastReceiverOnReceive;
      BroadcastReceiver.Add('android.intent.action.PHONE_STATE');
      BroadcastReceiver.Add('android.intent.action.READ_PHONE_STATE');
      BroadcastReceiver.RegisterReceive;

Вопросы снимаются, нашёл реализацию этого компонента на stackoverflow.

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

Ну, а что именно подчёркнуто? Если

BroadcastReceiverOnReceive

то и правильно, метода же нет у вас в классе, впишите свой

CheckPhoneCallState

 

или вот гляньте ответ http://stackoverflow.com/questions/33609494/how-to-check-and-hag-up-reject-incoming-outgoing-calls-on-android-in-delphi, там как раз по этому компоненту и очень похоже на ваш код...

 

АП.

Кстати, у @Rusland в той теме, тоже метода не хватает...

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

Всё понял, добавил:

procedure BroadcastReceiverOnReceive(csContext: JContext; csIntent: JIntent);

и

procedure TForm1.BroadcastReceiverOnReceive(csContext: JContext; csIntent: JIntent);
begin
  CheckPhoneCallState(csContext, csIntent);
end;

 

И после этого программа может заработать?

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

Так...

Значит пишите так:

      BroadcastReceiver:= TCSBroadcastReceiver.Create(nil);
      BroadcastReceiver.OnReceive := CheckPhoneCallState;
      BroadcastReceiver.RegisterReceive;
      BroadcastReceiver.Add('android.intent.action.PHONE_STATE');
      BroadcastReceiver.Add('android.intent.action.READ_PHONE_STATE');

Не сработает, тогда добавляйте такой код
      в секцию private

      procedure BroadcastReceiverOnReceive(csContext: JContext; csIntent: JIntent);


      далее в секцию implementation

      procedure TForm1.BroadcastReceiverOnReceive(csContext: JContext; csIntent: JIntent);
      begin
        CheckPhoneCallState(csContext, csIntent);
      end;

     
      в коде регистрации ресейвера
 

      BroadcastReceiver:= TCSBroadcastReceiver.Create(nil);
      BroadcastReceiver.OnReceive:= BroadcastReceiverOnReceive;
      BroadcastReceiver.RegisterReceive;
      BroadcastReceiver.Add('android.intent.action.PHONE_STATE');
      BroadcastReceiver.Add('android.intent.action.READ_PHONE_STATE');

 

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

 

Исходники - это файлы из корневой папки проекта, без подпапок, в которых собирается проект. Т.е. папка Android не нужна.

Далее, по коду.

Где у вас это?:

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  if Assigned(BroadcastReceiver) then
    BroadcastReceiver.Free;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  CreateBroadcastReceiver;
end;

Далее, на вибрацию нужно выставить пермишен "Vibrate" (на днях выложу на свой гитхаб, класс, упрощающий работу с вибрацией)

Менять местами код в регистрации ресейвера, смысла нет, делайте так как и было.

incomingCallNumber - вообще не понял, что это, где код, в котором вы заносите в эту переменную номер?

По поводу глобальных переменных -это уже придирка, но лучше пишите их в классе, как поля.

 

Вот в этом коде:

  if incomingCallNumber = 'номер телефона' then
    VibratorObj := SharedActivity.getSystemService(TJActivity.JavaClass.VIBRATOR_SERVICE);
  Vibrator := TJVibrator.Wrap((VibratorObj as ILocalObject).GetObjectID);
  Vibrator.vibrate(10);

словите ошибку, возможно AV, если звонок будет просто с другого номера.

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

Ваш архив перезалил, номер потёр.

 

Итог: Плохо копируете код.

Мой совет: Если не знаете, что делаете или просто не охото изучить представленные примеры, то лучше обратитесь в раздел Ищу подрядчика. Или можете попробовать помучить ещё форумчан, хотя вам дали примеры с избытком...

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

Исходники - это файлы из корневой папки проекта, без подпапок, в которых собирается проект. Т.е. папка Android не нужна.

Далее, по коду.

Где у вас это?:


procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  if Assigned(BroadcastReceiver) then
    BroadcastReceiver.Free;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  CreateBroadcastReceiver;
end;

Далее, на вибрацию нужно выставить пермишен "Vibrate" (на днях выложу на свой гитхаб, класс, упрощающий работу с вибрацией)

Менять местами код в регистрации ресейвера, смысла нет, делайте так как и было.

incomingCallNumber - вообще не понял, что это, где код, в котором вы заносите в эту переменную номер?

По поводу глобальных переменных -это уже придирка, но лучше пишите их в классе, как поля.

 

Вот в этом коде:


  if incomingCallNumber = 'номер телефона' then
    VibratorObj := SharedActivity.getSystemService(TJActivity.JavaClass.VIBRATOR_SERVICE);
  Vibrator := TJVibrator.Wrap((VibratorObj as ILocalObject).GetObjectID);
  Vibrator.vibrate(10);

словите ошибку, возможно AV, если звонок будет просто с другого номера.

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

Ваш архив перезалил, номер потёр.

 

Итог: Плохо копируете код.

Мой совет: Если не знаете, что делаете или просто не охото изучить представленные примеры, то лучше обратитесь в раздел Ищу подрядчика. Или можете попробовать помучить ещё форумчан, хотя вам дали примеры с избытком...

Все переделал по вашему кода, однако ничего не работает.

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

Со свежей головой. В дополнение к предыдущим замечаниям. Ну понеслась...

Что это такое?

      BroadcastReceiver.Add('android.intent.action.READ_PHONE_STATE');

Зачем это?

var
  telephonyService: JObject;
  telephonyManager: JTelephonyManager;
  ...
begin
  outputResult:= #13#10;

  telephonyService := TAndroidHelper.Context.getSystemService(TJContext.JavaClass.TELEPHONY_SERVICE);
  telephonyManager := TJTelephonyManager.Wrap((telephonyService as ILocalObject).GetObjectID);

Где определение статуса? (EXTRA_STATE_RINGING)

 

В общем, я внёс некоторые правки в ваш код и всё работает, но далее только в раздел Ищу подрядчика или ищите того, кто вам бесплатно реализует вашу задачу (сомневаюсь, что такие найдутся).

Call2.zip

Ссылка на комментарий
  • 0
В 03.12.2016 в 12:50, Andrey Efimov сказал:

Со свежей головой. В дополнение к предыдущим замечаниям. Ну понеслась...

Что это такое?


      BroadcastReceiver.Add('android.intent.action.READ_PHONE_STATE');

Зачем это?


var
  telephonyService: JObject;
  telephonyManager: JTelephonyManager;
  ...
begin
  outputResult:= #13#10;

  telephonyService := TAndroidHelper.Context.getSystemService(TJContext.JavaClass.TELEPHONY_SERVICE);
  telephonyManager := TJTelephonyManager.Wrap((telephonyService as ILocalObject).GetObjectID);

Где определение статуса? (EXTRA_STATE_RINGING)

 

В общем, я внёс некоторые правки в ваш код и всё работает, но далее только в раздел Ищу подрядчика или ищите того, кто вам бесплатно реализует вашу задачу (сомневаюсь, что такие найдутся).

Call2.zip

Спасибо большое за ответ. А ещё такой вопрос, я все-таки написал условие для определения номера, но если условие не выполняется, то нужно, чтобы программа ничего не делала. Тоесть в else мне нужно что-то написать, потому что при отсутствии else программа просто ввлетает и не работает. 

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

Спасибо большое за ответ. А ещё такой вопрос, я все-таки написал условие для определения номера, но если условие не выполняется, то нужно, чтобы программа ничего не делала. Тоесть в else мне нужно что-то написать, потому что при отсутствии else программа просто ввлетает и не работает. 

Эм... так если условие совпадения номера не выполняется, то и программа ничего не делает.

Как говорится: доверяй, но проверяй. Проверил на архиве, что скинул вам, добавил условие срабатывания вибрации по номеру и всё там нормально обрабатывается, ничего не вылетает.

Если номер совпадает - то вибрирует. Если нет, то не вибрирует.

Так что ищите ошибку в своём коде...

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

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

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

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

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

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

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

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

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

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

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