• 0
Rusland

"Общение" сервиса и приложения через intent

Вопросы

Пишут про некие intent, с помощью которых можно наладить "общение" между сервисом и приложением.

Расскажите как это делается? Поделитесь кодом, чтобы в голове прояснилось :)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

12 ответов на этот вопрос

  • -1

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0

Если речь про AndroidNotificationServiceDemo, то действительно не вижу никаких intent там. Вижу в сервисе вызов Notification через NotificationCenter1 и чтение из этого Notification в OnReceiveLocalNotification и все. 

Ищу в коде этого приложения "JIntent" и не нахожу.

 

Из-за непонимания, я скорее всего и задаю не верно вопрос.

Изменено пользователем Rusland

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 3

Для ищущих ответа:

Есть стандартное demo Object Pascal\Mobile Snippets\AndroidIntents\AndroidIntentsGroup.groupproj, в котором показано как из одного приложения передавать данные другому. С помощью этого примера удалось передавать данные из сервиса в основное приложение.

В юните основного приложения пишем:

uses FMX.Platform, FMX.Platform.Android, Androidapi.JNI.JavaTypes, Androidapi.JNI.Net, Androidapi.JNI.Os, 
  Androidapi.Helpers, System.Messaging, Androidapi.JNI.GraphicsContentViewText;

  private
    { Private declarations }
    function HandleAppEvent(AAppEvent: TApplicationEvent; AContext: TObject): Boolean; 
    procedure HandleActivityMessage(const Sender: TObject; const M: TMessage);  
    function HandleIntentAction(const Data: JIntent): Boolean;  

procedure TForm1.FormCreate(Sender: TObject);
var
  AppEventService: IFMXApplicationEventService;
begin
...
  if TPlatformServices.Current.SupportsPlatformService(IFMXApplicationEventService, AppEventService) then
    AppEventService.SetApplicationEventHandler(HandleAppEvent);

  // Register the type of intent action that we want to be able to receive.
  // Note: A corresponding <action> tag must also exist in the <intent-filter> section of AndroidManifest.template.xml.
  MainActivity.registerIntentAction(TJIntent.JavaClass.ACTION_VIEW);
  TMessageManager.DefaultManager.SubscribeToMessage(TMessageReceivedNotification, HandleActivityMessage);
end;


procedure TForm1.HandleActivityMessage(const Sender: TObject; const M: TMessage);
begin
  if M is TMessageReceivedNotification then
    HandleIntentAction(TMessageReceivedNotification(M).Value);
end;

function TForm1.HandleAppEvent(AAppEvent: TApplicationEvent; AContext: TObject): Boolean;
var
  StartupIntent: JIntent;
begin
  Result := False;
  if AAppEvent = TApplicationEvent.BecameActive then
  begin
    StartupIntent := MainActivity.getIntent;
    if StartupIntent <> nil then
      HandleIntentAction(StartupIntent);
  end;
end;

function TForm1.HandleIntentAction(const Data: JIntent): Boolean;
var
  Extras: JBundle;
begin
  Result := False;
  if Data <> nil then
  begin
    Memo1.ClearContent; // записываем в Memo пришедшее сообщение
    Extras := Data.getExtras;
    if Extras <> nil then
      Memo1.Text := JStringToString(Extras.getString(TJIntent.JavaClass.EXTRA_TEXT));
    Invalidate;
  end;
end;

в AndroidManifest.template.xml добавляем 

<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:mimeType="text/pas" />

Отправка сообщения из сервиса делается так:

SendTextViaIntent('Hello from service');

procedure TAndroidServiceDM.SendTextViaIntent(const AText: string);
var
  Intent: JIntent;
begin
  Intent := TJIntent.Create;
  Intent.setType(StringToJString('text/pas'));
  Intent.setAction(TJIntent.JavaClass.ACTION_VIEW);
  Intent.setFlags(TJIntent.JavaClass.FLAG_ACTIVITY_NEW_TASK); // добавил такой флаг, без  него сервис затыкался
  Intent.putExtra(TJIntent.JavaClass.EXTRA_TEXT, StringToJString(AText));
  if  TJContextWrapper.Wrap(System.JavaContext).getPackageManager.queryIntentActivities(Intent, TJPackageManager.JavaClass.MATCH_DEFAULT_ONLY).size > 0 then
     TJContextWrapper.Wrap(System.JavaContext).startActivity(Intent); // заменил MainActivity на TJContextWrapper.Wrap(System.JavaContext), т.к. это сервис
end;
Работает исправно, хоть 100%-ую правильность кода не гарантирую  :)

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

Попытался просто добавить FMX.Platform, в результате получаю ошибку в FMX.Platform.Android вываливается ошибка об использовании Activity внутри сервиса.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0

Установил приложение на планшет Lenovo Tab2 c Android 5.0.2 и теперь при отправке сообщения и сервиса появляется диалог с предложением открыть в моей программе или ES проводник :)

На что заменить android:mimeType ="text/pas" чтобы гарантированно ни одна программа не могла бы получать сообщение?

PS. Похоже ES проводник реагирует на слово text. Нужно его просто заменить (и в коде и в манифесте должно быть одинаково)

PPS. Заметил странную вещь, если вызывать из сервиса так

TTask.Run(procedure
begin
  try
    // что-то делаю
  finally
    TThread.Synchronize(nil, procedure 
    begin 
      EndTime:='Код ответа'; SendTextViaIntent(EndTime); // сюда не заходит 
    end);
  end; 
end);

то интент не передается

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0
Rusland
 
Спасибо большое, всё работает на ура. Вот только никак не могу добиться, чтоб сервис присылал сообщения втихую, не открывая приложения... Нет идей на эту тему?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0
В 19.01.2016в18:32, ZuBy сказал:

В стандартном примере все есть, в соседней теме выкладывал.

Форум я рыл, вроде, внимательно... Нельзя ли ссылку на тему?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0
12 часа назад, Adm123 сказал:

Форум я рыл, вроде, внимательно... Нельзя ли ссылку на тему?

Вы же читали сообщение Rusland, там написано где лежит пример...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0
6 минут назад, Andrey Efimov сказал:

Вы же читали сообщение Rusland, там написано где лежит пример...

Тут вышло недопонимание. Процитированный мной пост ZuBy вовсе не был обращен ко мне, но на тот момент почему-то отображался у меня последним. Видимо, форум после обновления не совсем "очнулся". Так что это не в счёт.

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0

Ну, ситуация с кодом выше такая, есть флаг

FLAG_ACTIVITY_NEW_TASK

он то и вызывает Активность, нужно попробовать использовать другие флаги, список есть тут http://developer.android.com/reference/android/content/Intent.html

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0

Да, я понимаю почему оно вылезает. И флаги пробовал. Просто тупо все поочередно ставил. Тогда сервис помирает...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0

Intents — это намерения.

Intent Filter — это желание обслуживать намерения.

Принял (приложением) отправленный Intent — будь добр запуститься и обработать это намерение.

 

Не подходят для этой задачи startActivity, нужно использовать BroadcastReceiver и отправлять ему свой Intent:

procedure TMainScreen.SomeOneSaysMeWhatIamStupidAndIsentHim;
Begin
	TAndroidHelper.Context.sendBroadcast(Intent);
End;

procedure TMainScreen.FormActivate(Sender: TObject);
begin
  begin
    try
      TAndroidHelper.Context.registerReceiver(FReceiver, FIntentFilter);
    finally

    end;
  end;
end;

procedure TMainScreen.FormDeactivate(Sender: TObject);
begin
  try
    TAndroidHelper.Context.unregisterReceiver(FReceiver);
  finally

  end;
end;

 

Изменено пользователем Pax Beach

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Для публикации сообщений создайте учётную запись или авторизуйтесь

Вы должны быть пользователем, чтобы оставить комментарий

Создать учетную запись

Зарегистрируйте новую учётную запись в нашем сообществе. Это очень просто!

Регистрация нового пользователя

Войти

Уже есть аккаунт? Войти в систему.

Войти

  • Похожий контент

    • От fredhack
      Доброго времени суток подскажите пожалуйста как мне получить ссылку из браузера запущенного через intent в общем суть такова:
      1 запускаю браузер через интент с сылкой http://fire-monkey.ru
      2 на ссылке происходит редирект
      3 я попадаю на http://fire-monkey.ru/forum/
      Как получить последнюю ссылку после редиректа? в данном случае она равна http://fire-monkey.ru/forum/
      var Intent: JIntent; begin Intent := TJIntent.Create; Intent.setAction(TJIntent.JavaClass.ACTION_VIEW); Intent.setData(StrToJURI('http://fire-monkey.ru')); SharedActivity.startActivity(Intent); end;  
    • От x11
      На основе нескольких тем форума сделал службу перехвата звонков и номера телефона.
      http://fire-monkey.ru/topic/3878-статьякак-создать-простой-android-broadcast-receiver-how-to-implement-simplest-android-broadcast-receiver-in-delphi/
      http://fire-monkey.ru/topic/2386-перехват-события-звонка/
      http://fire-monkey.ru/topic/2972-использование-нативных-localbroadcastmanager-и-broadcastreceiver/
      Покритикуйте пожалуйста. Уверен, что не всё правильно.
      Но что до ума не удалось довести, так это то, как правильно останавливать службу и закрывать приложение.
      Проект (для Токио) приложил теме.
      Заранее благодарен.
       
      BR2.rar
    • От A. Sharif
      Возможно ли с помощью intent получить от какого-либо из официальных приложений Вконтакте/Фейсбук/Инст/Google access-token (через кол-бэк метод)?
      Предусматривается ли данная возможность этими приложениями? Если кто делал - приведите, пожалуйста, пример получения результата. 
    • От Wovan2
      Здравствуйте.
      Пишу на Delphi 7. И все было нормально пока не у нас не появился терминал сбора данных на Androide. На Delphi 10 написал простенькое приложение. Но тут встала проблема с занесением данных в поле ввода со сканера штрихкода. В инете нашел, что это дело просто решается интентами. Вообще в windows я подобное делал: вешал процесс, следящий за com-портом, и при появлении данных на нем пересылал их куда надо. В Android должно быть не сложнее. Но я запутался во всей этой куче параметров и функций, передаваемых и получаемых "намерениями".
      В общем вот что мы имеем на данный момент.
      В настройках сканера прописано:
       
      Intent output - android.intent.ACTION_DECODE_DATA Intent string extra - barcode_string На просторах нашел запуск BroadcastReceiver.
      На событие получения сообщения повесил 
      ed.Text := JStringToString(csIntent.getExtras.getString(TJIntent.JavaClass.EXTRA_INTENT)); где csIntent параметр из  BroadcastReceiverOnReceive(csContext: JContext; csIntent: JIntent); Но ничего не выходит. 
      Я подозреваю, что данные из сканера где-то в структуре csIntent. Но, к сожалению, в отладке дальше адреса этой переменной пробраться не получилось.
      Причем строка ed.Text := JStringToString(csIntent.getAction); возвращает в Text название интента: "android.intent.ACTION_DECODE_DATA".
      Помогите разобраться со структурой JIntent. Спасибо.
       
       
    • От Rustam Bikeev
      Здравствуйте. Пришла беда откуда не ждал, Delphi 10.2 не знает библиотеки androidapi.... FMX.Helpers.... и тд и тп. И никак не получается их установить, либо я тупой либо я даже незнаю что может быть. фалы *.dcu лежат в папке ...\lib\android\release.
      Помогите решить проблему очень нужно использовать намерения. уже и переустанавливал платформу android не помогает.

    • От AlexShaman
      procedure TfMain.PhotoClick(Sender: TObject); var sPath,FLastPhotoName:string;   {$IF DEFINED(ANDROID)}   PhotoIntent: JIntent;   photoUri: Jnet_Uri;   JFileName: JFile;   {$ENDIF} begin   {$IF DEFINED(ANDROID)}   FLastPhotoName := '';   FLastPhotoFullName := '';   FMessageSubscriptionID := TMessageManager.DefaultManager.SubscribeToMessage(TMessageResultNotification, HandleActivityMessage);   PhotoIntent := TJIntent.JavaClass.init(TJMediaStore.JavaClass.ACTION_IMAGE_CAPTURE);   if (PhotoIntent.resolveActivity(TAndroidHelper.Context.getPackageManager()) <> nil) then   begin     FLastPhotoName := THashMD5.GetHashString('JPEG PHOTO FILE ' + DateTimeToStr(Now)) + '.jpg';     FLastPhotoFullName := TPath.Combine(TPath.GetSharedDocumentsPath, FLastPhotoName);     JFileName := TJFile.JavaClass.init(StringToJString(FLastPhotoFullName));     photoUri := TJnet_Uri.JavaClass.fromFile(JFileName);     PhotoIntent.putExtra(TJMediaStore.JavaClass.EXTRA_OUTPUT,         TJParcelable.Wrap((photoUri as ILocalObject).GetObjectID));     if PhotoIntent.resolveActivity(TAndroidHelper.Activity.getPackageManager) <> nil then       TAndroidHelper.Activity.startActivityForResult(PhotoIntent, REQUEST_IMAGE_CAPTURE);   end;   {$ENDIF}  
      Приложение камеры открывается, фото делается, но при закрытии приложение вылетает
      В логах ошибки
      java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=1, result=-1, data=null} to activity {com.embarcadero.test/com.embarcadero.firemonkey.FMXNativeActivity}: java.lang.NullPointerException
       
    • От ENERGY
      Подскажите пожалуйста как определить что программа запустилась из AlarmManager?
      Я сделал это так, по аналогии с http://stackoverflow.com/questions/6751564/how-to-pass-a-boolean-between-intents
      В Java коде, который компилиться в итоге в classes.dex (с XE7 не нужен DEX файл, можно подключить Jar файл сразу к проекту!), добавил строчку
      public class AlarmReceiver extends BroadcastReceiver {
          public void onReceive(Context context, Intent intent) {
                  Intent TestLauncher = new Intent();                        
                  TestLauncher.setClassName(context, "com.embarcadero.firemonkey.FMXNativeActivity");
                  TestLauncher.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                  TestLauncher.putExtra("StartedFromAM", true);
                  context.startActivity(TestLauncher);
          }
      }
      По идее теперь при старте из AlarmManager, должно быть true в активити.
      Из Delphi пытаюсь получить это значение, но всегда возвращает false (0). 
       ShowMessage(SharedActivity.getIntent.getBooleanExtra(StringToJString('StartedFromAM'), false).ToString );
      И вот так тоже:
      ShowMessage ( MainActivity.getIntent.getBooleanExtra(StringToJString('StartedFromAM'), false).ToString);
      Не подскажете в чем может быть проблема?

       
    • От M1shQa
      Подкинуло начальство  задачку, да не простую. Приложение должно в фоне мониторить gps, собирать данные о батарее, логировать и потом сливать на сервер. Все это будет нащадно жрать батарею, понимаю, но начальству нужен именно этот вариант. Перейду к вопросам:
      1.Нужно пилить сервис, но исходя из прошлых тем - таймер не работает, слипы не вариант, как сделать так, чтоб сервис просыпался каждые 5 минут/15 минут/ 1 час ?
      2.Мониторинг GPS, тут решение вроде нашел в этой ветке для seattle, как лучше всего собирать и хранить данные для отправки? (до этого все сохранял в простых .txt)
      3.Работают ли компоненты indy корректно в сервисе? срабатывают ли except'ы и как правильно мониторить подключение к сети? 
      Проблема еще и в том, что программа должна работать более менее стабильно и если опыт написания простых приложений у меня есть, то с сервисами уже пару месяцев не могу подружиться..
      Всем бобра!
    • От Pax Beach
      В Android 6 на Berlin 10.1.1 перестала работать стандартная функция TakePhotoFromCameraAction.

      Иногда работает, иногда нет.
      Поэтому я решил написать нативную замену этой функции. За основу взят пример с портала разработчиков Android.
      Мой пример про видео на базе отправки Intetn смартфону и получение результата в виде другого Intent, отлично работает.
      Но для фотографий этот пример сыпется, после выполнения фотографирования система возвращается в мое приложение и оно вылетает с ошибкой:
      Если заглянуть в исходнки, там все обвязано сообщениями в лог монитора. Последнее сообщение «+ Intent is sent».
      Помогите пожалуйста разобраться, в чем может быть проблема?
       
      PhotoIntent.zip
    • От Pax Beach
      Знающие люди, подскажите пожалуйста, как в iOS одно приложение может запустить другое приложение, как передать картинку в другое приложение, готовое его принять, как при запуске обрабатывать в своем приложении параметры, переданные из другого приложения?
      В Android для этого есть механизм Intent Filter, а как это устроено в iOS, и как с этим работать в RAD Studio?
       
  • Последние посетители   0 пользователей онлайн

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