Erklärung des Android-Bindungsdienstes und prozessübergreifende Kommunikation

** **.

Erklärung des Android-Bindungsdienstes und prozessübergreifende Messenger-Kommunikation

** Der
Android-Dienst ist ein Programm, das im Hintergrund ausgeführt wird. Um es klar zu sagen, es gibt keine Benutzeroberfläche. Hier möchte ich betonen, dass das Ausführen im Hintergrund nicht das Ausführen in einem Nicht-Haupt-Thread bedeutet. Mit Ausnahme von IntentService, wenn Sie dies tun Starten Sie keinen neuen Dienst, normalen Dienst-Thread, dann wird standardmäßig im Haupt-Thread ausgeführt.
Es gibt zwei Möglichkeiten, einen Dienst zu starten: eine ist gebunden und die andere ist gestartet. Es gibt einige Unterschiede zwischen den beiden Startmethoden. Es sollte beachtet werden, dass beim Binden des Bindedienstes bis zum letzten Programm von der Bindung an den Dienst die Bindung aufgehoben wird, andernfalls wird der Dienst weiterhin ausgeführt. Bei der Startmethode des Startdienstes müssen Sie nach dem Start den Dienst selbst stoppen oder stopSelf innerhalb des Dienstes aufrufen, da sonst der Dienst nicht geschlossen wird.
Auch muss auf den Lebenszyklus geachtet werden, wird dieses beigefügte Bild vollständig verstehen.
Schreiben Sie hier eine Bildbeschreibung
Es ist zu beachten, dass die onCreate-Methode beim Starten des Dienstes nur einmal aufgerufen wird und beim Starten des Dienstes direkt zu onStartCommand () oder onBind () wechselt.

Okay, lass uns aufhören Unsinn zu reden, lass uns eine Demo machen:

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 erbt das untergeordnete IntentService, seine Funktion ist sehr einfach, es besteht darin, eine Zeile "Intent Service Start" zu drucken. Das Besondere ist, dass dieser Dienst, wie oben erwähnt, auf einem Nicht-Haupt-Thread ausgeführt wird.

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 kann von startService () und auch von bindService gestartet werden. Hier geht es hauptsächlich um die Startmethode von bindService. Wenn wir an einen Dienst binden, rufen wir die onBind-Methode zurück, die eine IBinder-Klasse zurückgibt. Diese Klasse persönlich fühlt sich an wie der Proxy-Modus, über den die Methode im Dienst aufgerufen werden soll. Wenn wir den Dienst binden, müssen wir den Parameter ServiceConnection übergeben. In diesem Objekt befinden sich zwei Rückrufmethoden. Eine ist ublic void onServiceConnected (Name des Komponentennamens, IBinder service) Einer ist public void onServiceDisconnected (Name des Komponentennamens), der Parameter service in onServiceConnected ist der IBinder, den wir in der onBind-Methode zurückgeben, und durch Transformation können wir die Methode im entsprechenden Service aufrufen. Also habe ich hier eine interne Klasse NormalBinder geschrieben, damit "" bind method "gedruckt und in der onBind-Methode zurückgegeben, damit ich diesen NormalBinder in MainActivity abrufen und seine internen Methoden aufrufen kann.

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


}

Für diesen Prozess wollte ich ein schematisches Diagramm zeichnen, aber ich war zu faul, deshalb habe ich beschlossen, es im Text zu belassen.
Es gibt zwei Arten der prozessübergreifenden Kommunikation: Die eine ist AIDL und die andere ist die Verwendung von Messenger. Der Unterschied zwischen diesen beiden Methoden besteht darin, dass AIDL Multithread-fähig ist, während Messenger Single-Threaded ist, was bedeutet, dass Messenger verwendet wird Thread-übergreifend. Die Prozesskommunikation enthält jeweils nur eine Anforderung in der Nachrichtenwarteschlange. Beachten Sie, dass Sie, wenn der Server Daten an den Client zurücksenden muss, den Messenger des Clients in der öffentlichen void handleMessage-Methode (Message msg) des Handlers abrufen müssen. Dieser Messenger ist Messenger clientMessenger = msg.replyTo; dies befindet sich auf dem Client Parameter, die beim Senden einer Nachricht an den Server an die Nachricht übergeben werden.

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

Anschließend initiiert MainAcitivyt eine bindService-Anforderung. (Hierbei ist zu beachten, dass nach 5.0 die Absicht, die den Dienst öffnet, die angezeigte Absicht sein muss, sodass Ihre Absicht Informationen über den Paketnamen eines anderen Programms enthalten muss.) OnServiceConnected in ServiceConnection In der Methode Holen Sie sich den entsprechenden Messenger über den zurückgegebenen 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;
        }
    };

Ich denke du magst

Origin blog.csdn.net/skateboard1/article/details/51253116
Empfohlen
Rangfolge