Объяснение службы привязки Android и межпроцессное взаимодействие

**

Описание службы привязки Android и межпроцессное взаимодействие в Messenger

**
Служба Android - это программа, которая работает в фоновом режиме. Проще говоря, интерфейса нет. Здесь я хочу подчеркнуть, что работа в фоновом режиме не означает выполнение в неосновном потоке. За исключением IntentService, если вы не запускайте новую службу, обычный поток службы, тогда по умолчанию запускается в основном потоке.
Есть два способа запустить службу: один - привязать, а другой - запустить.Между этими двумя методами запуска есть довольно много различий. Следует отметить, что когда bind связывает службу, до тех пор, пока последняя программа из привязки к службе не вызывает unbind, в противном случае служба будет продолжать работать. Что касается метода запуска startservice, после того, как он запущен, вам нужно самостоятельно stopService или вызвать stopSelf внутри службы, иначе служба не будет закрыта.
Также нужно обратить внимание на жизненный цикл сервиса, это приложенная картинка будет полностью понятна.
Напишите здесь описание изображения
Следует отметить, что метод onCreate вызывается только один раз при запуске службы, а затем, когда вы запускаете службу, он переходит непосредственно к onStartCommand () или onBind ().

Ладно, давайте перестанем говорить чушь, возьмем демонстрацию:

public class MainActivity extends AppCompatActivity implements View.OnClickListener{
    
    

    private boolean hasBound;
    private Button intent_Service;
    private Button start_Service;
    private Button bind_Service;
    private Button messenger_Service;
    //下面的handler和Messenger使用来进行跨进程通信的
    private Handler handler=new Handler()
    {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            if(msg.what==322)
            {
                Toast.makeText(getApplicationContext(),"receive message from server",Toast.LENGTH_SHORT).show();
            }
        }
    };

    private Messenger clientMessenger=new Messenger(handler);
    private Messenger serverMessenger;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
    }

    private void initView()
    {
        intent_Service= (Button) findViewById(R.id.intent_service);
        intent_Service.setOnClickListener(this);
        start_Service= (Button) findViewById(R.id.start_service);
        start_Service.setOnClickListener(this);
        bind_Service=(Button)findViewById(R.id.bind_service);
        bind_Service.setOnClickListener(this);
        messenger_Service=(Button)findViewById(R.id.messenger_service);
        messenger_Service.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch(v.getId())
        {
            case R.id.intent_service:
            //启动IntentService
                Intent intentService=new Intent(this,IntentTestService.class);
                startService(intentService);
                break;
            case R.id.start_service:
            //start调用普通Sservice
                Intent startService=new Intent(this,NormalService.class);
                startService(startService);
                break;
            case R.id.bind_service:
            //bind调用service
                Intent bindService=new Intent(this,NormalService.class);
                if(bindService.resolveActivity(getPackageManager())!=null)
                bindService(bindService,connection,BIND_AUTO_CREATE);
                break;
//利用Messenger进行跨进程通信
            case R.id.messenger_service:
                if(!hasBound) {
                    Intent intent = new Intent("com.skateboard.serverservice.service.BIND");
                    intent.setPackage("com.skateboard.serverservice");
                    bindService(intent, messengerConnection, Context.BIND_AUTO_CREATE);
                }
                else
                {
                    sendMessageToServier();
                }
                break;
        }
    }



    private ServiceConnection messengerConnection=new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            hasBound=true;
            serverMessenger=new Messenger(service);
            Message message=new Message();
            message.what=233;
            message.replyTo=clientMessenger;
            try {
                serverMessenger.send(message);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
          hasBound=false;
        }
    };

    private ServiceConnection connection=new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            NormalService.NormalBinder binder= (NormalService.NormalBinder) service;
            binder.bindMethod();
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    };

    private void sendMessageToServier()
    {
        Message message=new Message();
        message.what=233;
        message.replyTo=clientMessenger;
        try {
            serverMessenger.send(message);
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
    }
}

IntentTestService наследует дочерний IntentService, его функция очень проста, это вывод строки «намерение запуска службы». Что еще более особенно, так это то, что, как упоминалось выше, эта служба работает в неосновном потоке.

public class IntentTestService extends IntentService {
    
    


    public IntentTestService()
    {
       super("IntentTestService");
    }

    /**
     * Creates an IntentService.  Invoked by your subclass's constructor.
     *
     * @param name Used to name the worker thread, important only for debugging.
     */
    public IntentTestService(String name) {
        super(name);
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        System.out.println("intent service start");
    }
}

NormalService может быть запущен с помощью startService (), а также может быть запущен с помощью bindService. Здесь мы в основном говорим о стартовом методе bindService. Когда мы привязываемся к службе, мы вызываем метод onBind, который вернет класс IBinder. Этот класс лично чувствует себя как режим прокси, через который вызывается метод в службе, когда мы связываем службу, нам нужно передать параметр ServiceConnection, в этом объекте есть два метода обратного вызова, один - ublic void onServiceConnected (имя ComponentName, IBinder service) Один из них - public void onServiceDisconnected (имя ComponentName), служба параметров в onServiceConnected - это IBinder, который мы возвращаем в методе onBind, и, преобразовав его, мы можем вызвать метод в соответствующей службе. Итак, здесь я написал внутренний класс NormalBinder, использую его для печати "" метода привязки "и возврата его в методе onBind, чтобы я мог получить этот NormalBinder в MainActivity и вызвать его внутренние методы.

public class NormalService extends Service {
    
    
    public NormalService() {
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        System.out.println("service start");
        stopSelf();
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        NormalBinder normalBinder=new NormalBinder();
        return normalBinder;

    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        System.out.println("stop service");
    }

    public class NormalBinder extends Binder
    {
    
    
        public void bindMethod()
        {
            System.out.println("bind method");
        }
    }


}

Для этого процесса я хотел нарисовать схематическую диаграмму, но мне было лень, поэтому я решил оставить ее в тексте.
Существует два способа межпроцессного взаимодействия: один - AIDL, а другой - использовать Messenger. Разница между этими двумя методами заключается в том, что AIDL является многопоточным, а Messenger - однопоточным, что означает, что он использует Messenger для Взаимодействие между потоками имеет только один запрос в очереди сообщений. Обратите внимание, что если вам нужен сервер для отправки данных обратно клиенту, вам необходимо получить клиентский Messenger в общедоступном методе обработчика void handleMessage (Message msg). Этот мессенджер называется Messenger clientMessenger = msg.replyTo; он находится на клиенте The параметры, передаваемые сообщению при отправке сообщения на сервер.

public class ServerService extends Service {
    
    

    private Handler handler=new Handler()
    {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            if(msg.what==233)
            {
                Messenger clientMessenger=msg.replyTo;
                Message message=new Message();
                message.what=322;
                try {
                    clientMessenger.send(message);
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
        }
    };

    private Messenger messenger=new Messenger(handler);

    public ServerService()
    {

    }

    @Override
    public void onCreate() {
        super.onCreate();
        System.out.println("service create");
    }

    @Override
    public IBinder onBind(Intent intent) {
        System.out.println("bind service");
       return messenger.getBinder();
    }
}

Затем MainAcitivyt инициирует запрос bindService. (Здесь следует отметить, что после версии 5.0 намерение, открывающее службу, должно быть отображаемым намерением, поэтому ваше намерение должно содержать информацию о имени пакета другой программы.) OnServiceConnected в ServiceConnection В методе , получите соответствующий Messenger через возвращенный IBinder

 private ServiceConnection messengerConnection=new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            hasBound=true;
            serverMessenger=new Messenger(service);
            Message message=new Message();
            message.what=233;
            message.replyTo=clientMessenger;
            try {
                serverMessenger.send(message);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
          hasBound=false;
        }
    };

рекомендация

отblog.csdn.net/skateboard1/article/details/51253116