Взаимодействие между приложением и службой

    Введение


    В данной публикации хочу показать пример взаимодействия (получение и отправки данных) приложения и службы, в операционной системе Андроид. Публикация рассчитана на начинающих программистов, теории практически не будет, так как основная цель рассказать, как это сделать.


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

    Перед тем как начать, у вас должны быть установлены основные компоненты для создания Андроид приложений, такие как Java (JDK и JRE), Eclipse, Android SDK и плагин ADT для Eclipse, о том, как это установить и настроить вы можете прочесть на страницах Хабрахабр.

    1. Создаем приложение и службу


    Запускаем Eclipse, далее нажимаем Ctrl+N, в появившемся диалоговом окне выбираем пункт «Android Project» и следуем инструкции, показанной на изображении:



    Тем самым мы создали каркас приложения, теперь нужно добавить службу, для этого необходимо создать новый класс, наследованный от класса Service, нажимаем правой кнопкой мыши по пакету нашего проекта:



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



    Теперь добавим наш сервис в файл AndroidManifest.xml, для этого открываем его в Eclipse и делаем следующее:



    2. Получение информации от службы


    Для получения информации от службы, необходимо зарегистрировать приемник широковещательных сообщений, для этого добавим соответствующий код в методы onCreate и onDestroy приложения:

    @Override
    public void onCreate(Bundle savedInstanceState) 
    {
    	super.onCreate(savedInstanceState);
    	setContentView(R.layout.main);
    	//Регистрация приемника
    	IntentFilter filter = new IntentFilter();
    	filter.addAction("AppService");
    	service = new BroadcastReceiver() 
    	{
    		@Override
    		public void onReceive(Context context, Intent intent) 
    		{
    			if(intent.getAction().equals("AppService"))
    			{
    				Log.i("AppService",intent.getStringExtra("Data"));
    			}
    		}
    	};
    	registerReceiver(service, filter);
            //Запуск службы
            startService(new Intent(this,MainService.class));
    	
    }
    @Override
    protected void onDestroy()
    {	
    	super.onDestroy();
    	if(service!= null){unregisterReceiver(service);}
    	stopService(new Intent(this,MainService.class));
    }
    


    В службе, информация передается путем отправки широковещательного сообщения, добавим метод onCreate и отправку:

    @Override
    public void onCreate()
    {
    	super.onCreate();
    	Intent in = new Intent("AppService");
    	in.putExtra("Data","Служба запущена.");
    	sendBroadcast(in);
    }
    


    Запускаем наше приложение и видим в LogCat информацию, полученную от службы и обработанную в основном коде приложении:



    3. Передача данных службе


    Теперь добавим механизм AIDL к нашему проекту, для этого добавим файл с расширение aidl:



    Появится диалоговое окно, в котором вводим следующие данные:



    Откроется окно редактирования файла UpdateService.aidl, добавляем следующий код:

    package ru.blagin.appservice;
    
    interface UpdateService 
    {
            String UpdateSrv(String strTest);
    }
    


    После чего необходимо сохранить изменения и пересобрать проект, если отключена опция автоматической сборки, далее ADT плагин автоматически сгенерирует код, необходимый для работы данного механизма. Теперь нужно изменить код основного приложения и службы. Добавим реализацию интерфейса ServiceConnection в основной код приложения, изменим запуск и остановку службы, а так же добавим кнопку, при нажатии на которую будет осуществлена передача данных:

    package ru.blagin.appservice;
    
    import android.app.Activity;
    import android.content.BroadcastReceiver;
    import android.content.ComponentName;
    import android.content.Context;
    import android.content.Intent;
    import android.content.IntentFilter;
    import android.content.ServiceConnection;
    import android.os.Bundle;
    import android.os.IBinder;
    import android.os.RemoteException;
    import android.util.Log;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.widget.Button;
    import ru.blagin.appservice.UpdateService;
    
    public class Main extends Activity 
    {
    	private BroadcastReceiver brService = null;
    	
    	UpdateService iService = null;
    	private ServiceConnection mConnection = new ServiceConnection() 
    	{
    		public void onServiceDisconnected(ComponentName name)
    		{
    			iService = null;
    		}
    		public void onServiceConnected(ComponentName name, IBinder service)
    		{
    			iService = UpdateService.Stub.asInterface(service);
    		}
    	};
        @Override
        public void onCreate(Bundle savedInstanceState) 
        {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
                  	
          	//Регистрация приемника
            	IntentFilter filter = new IntentFilter();
    		filter.addAction("AppService");
    		brService = new BroadcastReceiver() 
    		{
    			@Override
    			public void onReceive(Context context, Intent intent) 
    			{
    				if(intent.getAction().equals("AppService"))
    				{
    					Log.i("AppService",intent.getStringExtra("Data"));					
    				}
    		    }
    		};
    		registerReceiver(brService, filter);
    		
    		//Запуск службы
          	bindService(new Intent(this,MainService.class),mConnection,BIND_AUTO_CREATE);
          
          	Button bt = (Button)findViewById(R.id.buttonSend);
          	bt.setOnClickListener(new OnClickListener()
    		{
    			public void onClick(View v)
    			{
    				//Отправляем данные
    				try
    				{
    		        	String strResult = iService.UpdateSrv("String from app");
    		        	Log.i("AppService",strResult);
    		        	
    				}catch(RemoteException e){Log.e("AppService",e.getMessage());}
    			}
    		});
        }
        @Override
        protected void onDestroy()
        {	
        	super.onDestroy();
        	if(brService!= null){unregisterReceiver(brService);}
        	if(mConnection!= null){unbindService(mConnection);}
        }
    }
    


    Внесем изменения в код службы:

    package ru.blagin.appservice;
    
    import android.app.Service;
    import android.content.Intent;
    import android.os.IBinder;
    import android.os.RemoteException;
    
    public class MainService extends Service
    {
    	Intent in = null;
    	@Override
    	public void onCreate()
    	{
    		super.onCreate();
    		in = new Intent("AppService");
    		in.putExtra("Data","Служба запущена.");
            	sendBroadcast(in);
    	}
    	@Override
    	public IBinder onBind(Intent intent)
    	{
    	    return new UpdateService.Stub() 
    	    {
    			public String UpdateSrv(String strTest) throws RemoteException
    			{
    				strTest = strTest + " and service.";
    				in.putExtra("Data","Вызов метода интерфейса.");
    		        	sendBroadcast(in);
    				return strTest;
    			}
    	    };
    	}
    	@Override
    	public void onDestroy()
    	{
    		super.onDestroy();
    	}
    }
    


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



    Заключение


    Надеюсь, эта небольшая статья поможет вам в дальнейшем уже глубже разобраться в механизмах взаимодействия и работы приложений в операционной системе Андроид. Хотелось еще раз отметить, что данный текст, создавался исключительно для начинающих программистов и главным критерием, написания, было ответить на вопрос «Как это сделать?».

    Исходный код приложения.

    Список используемой литературы


    1. Pro Android 3 — Satya Komatineni, Dave MacLean, Sayed Hashimi, 2011 г.
    2. AIDL (Android Interface Definition Language) и коммуникация между процессами (IPC) (umobisoft).
    Метки:
    Поделиться публикацией
    Похожие публикации
    Реклама помогает поддерживать и развивать наши сервисы

    Подробнее
    Реклама
    Комментарии 18
    • +3
      Плохой код -стайл. Если вы пишите для начинающих, ваш код должен быть совершенным и не допускать например такого:

      service = new BroadcastReceiver()

      Так же куча расхождений с соглашениями Java.
      • 0
        Согласен с вами, буду исправляться.
        • 0
          Вы пришли с C#, или мне показалось?
        • 0
          Я начинающий. Скажите, что не так в такой строчке?
          • 0
            имя переменной вводит в заблуждение. Кажется, что это Service, а на самом деле это BroadcastReceiver. Правильное имя либо receiver, либо serviceIntentReceiver.
            • 0
              Вы достаточно быстро войдёте в курс дела, если поставите Checkstyle на Eclipse. Об этом тоже написано в Хабре. И спасибо за статью.
          • +2
            Есть вопросы:
            1. Название: «Взаимодействие между приложением и службой»
            а в статье не очень понятно рассказываться про AIDL, который используется реже всего из всех способов взаимодействия
            2. Не рассказано в каких случаях и почему надо использовать AIDL
            3. Если бы я забыл все про AIDL и притворился «начинающим программистом» я бы не понял ни что такое AIDL, ни как я могу его использовать. А ваше приложение и с помощью Itent'ов отлично стрингами перебрасыватся…
            П.С. а как рисовать такие красивые красные рамки, которыми вы помечали все важные моменты на скриншотах?
            • 0
              Отвечу за автора на ПыСы. Хотя сам автор мог использовать другой софт.
              greenshot
              • 0
                1. В начале упомянул, что теории практически не будет. Все таки нужно было расписать, что к чему.
                2. Да верно, пытался ответить на вопрос «как это сделать?» а нужно было на вопрос «а зачем?».
                3. Верно сказано, мне уже объяснили, что есть способы намного лучше и проще.
                Рамки делались в фотошопе, хотя подойдет любой графический редактор, например под эти цели хорошо подойдет QipShot.
              • 0
                Да тут и совершенно без AIDL`a можно обойтись. Зачем новичков учить г… ну, вы поняли.
                в onBind возвращаем обычный биндер, в onServiceConnected биндер кастуем к нужному типу и через его метод выдираем сам сервис.
                • 0
                  if(intent.getAction().equals("AppService")) — и вот это лишнее
                  • 0
                    Это полезный код, если сервисов несколько. Другое дело, надо было прояснить этот момент.
                    • 0
                      Не сервисов несколько, а несколько Intent-фильтров. Тогда да. А так он всего один
                  • +1
                    Да, вы правы, мне уже объяснили, что есть способы намного проще и лучше.
                  • +1
                    Да, на андроидовском взаимодействие между приложениями и службой и черт споткнётся. Сам помню одну апп три раза переписывал, чтоб разобраться. А хороший топик, как и с чем это кушать — теория и практика, был бы очень полезн.
                    • 0
                      Ринулся было коммент писать, вчера только писал подобный код и ни о каком AIDL слыхом не слыхивал. У меня все построено на Messenger'ах и прекрасно работает и выглядит гораздо проще, как мне кажется.

                      На всякий случай, если кому-то хочется посмотреть, вот ссылка на сервис, а вот код активити

                      • 0
                        В смысле, ринулся писать коммент с критикой, но потом увидел, что народ уже все подробно расписал.
                      • 0
                        Для получения информации от службы, необходимо зарегистрировать приемник широковещательных сообщений, для этого добавим соответствующий код в методы onCreate и onDestroy приложения:


                        наверное всё-таки активити, а не приложения?

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