Explicación del servicio de enlace de Android y comunicación entre procesos

**

Explicación del servicio de enlace de Android y comunicación entre procesos de Messenger

** El
servicio de Android es un programa que se ejecuta en segundo plano. Para decirlo sin rodeos, no hay interfaz. Aquí quiero enfatizar que ejecutar en segundo plano no significa ejecutar en un hilo no principal. Excepto por IntentService, si no inicie un nuevo servicio, subproceso de servicio normal, entonces el valor predeterminado es ejecutarse en el subproceso principal.
Hay dos formas de iniciar un servicio, una es vincular y la otra es iniciar Hay bastantes diferencias entre los dos métodos de inicio. Debe tenerse en cuenta que cuando se vincula el servicio se vincula, hasta que el último programa de vinculación a las llamadas de servicio se desvincula; de lo contrario, el servicio continuará ejecutándose. En cuanto al método de inicio de startservice, una vez que se inicia, debe detener el servicio usted mismo o llamar a stopSelf dentro del servicio; de lo contrario, el servicio no se cerrará.
También es necesario prestar atención al ciclo de vida del servicio, esta imagen adjunta se entenderá completamente.
Escriba la descripción de la imagen aquí
Cabe señalar que el método onCreate solo se llama una vez cuando inicia el servicio, y luego, cuando inicia el servicio, irá directamente a onStartCommand () o onBind ().

De acuerdo, dejemos de decir tonterías, hagamos una demostración:

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 hereda el hijo IntentService, su función es muy simple, es imprimir una línea de "inicio de servicio de intención". Lo que es más especial es que, como se mencionó anteriormente, este servicio se ejecuta en un hilo no principal.

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 puede ser iniciado por startService () y también puede ser iniciado por bindService. Aquí hablamos principalmente sobre el método de inicio de bindService. Cuando nos vinculamos a un servicio, volvemos a llamar al método onBind, que devolverá una clase IBinder. Esta clase personalmente se siente como el modo proxy, a través del cual llamar al método en el servicio, cuando vinculamos el servicio, necesitamos pasar un parámetro, ServiceConnection, hay dos métodos de devolución de llamada en este objeto, uno es ublic void onServiceConnected (ComponentName name, IBinder service) Uno es public void onServiceDisconnected (ComponentName name), el parámetro service en onServiceConnected es el IBinder que devolvemos en el método onBind, y al transformarlo, podemos llamar al método en el servicio correspondiente. Así que aquí escribí una clase interna NormalBinder, la utilicé para imprimir "" método de enlace "y lo devolví en el método onBind, de modo que pueda obtener este NormalBinder en MainActivity y llamar a sus métodos internos.

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");
        }
    }


}

Para este proceso, quería dibujar un diagrama esquemático, pero era demasiado vago, así que decidí mantenerlo en texto.
Hay dos formas de comunicación entre procesos, una es AIDL y la otra es usar Messenger. La diferencia entre estos dos métodos es que AIDL es multiproceso, mientras que Messenger es de un solo subproceso, lo que significa que usa Messenger para La comunicación del proceso tiene solo una solicitud a la vez en la cola de mensajes. Tenga en cuenta que si necesita que el servidor envíe datos al cliente, debe obtener el Messenger del cliente en el método public void handleMessage (Message msg) del controlador. Este messenger es Messenger clientMessenger = msg.replyTo; esto está en el cliente El parámetros pasados ​​al mensaje al enviar un mensaje al servidor.

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();
    }
}

Luego MainAcitivyt inicia una solicitud de bindService. (Cabe señalar aquí que después de 5.0, el Intent que abre el servicio debe ser el Intent mostrado, por lo que su Intent debe contener información sobre el nombre del paquete de otro programa). OnServiceConnected en ServiceConnection En el método , obtenga el Messenger correspondiente a través del IBinder devuelto

 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;
        }
    };

Supongo que te gusta

Origin blog.csdn.net/skateboard1/article/details/51253116
Recomendado
Clasificación