zoukankan      html  css  js  c++  java
  • Android 使用binder访问service的方式

    binder机制是贯穿整个Android系统的进程间访问机制,经常被用来访问service,我们结合代码看一下binder在访问service的情形下是怎么具体使用的。

    service 你可以理解成没有的界面的activity,它是跑在后台的程序,所谓后台是相对于可以被看得到的程序的,后台程序是不能直接交互的程序。

    binder主要是用来进程间通信的,但也可用在和本地service通信。

    1. 我们先来看一个与本地service通信的例子。

    package com.ckt.wangxin;
    
    import android.app.Service;
    import android.content.Intent;
    import android.os.Binder;
    import android.os.IBinder;
    import android.widget.Toast;
    /**
     * This is a service stub for both LocalBinderClient
     * and RemoteBinderClient 
     * @author Wang Xin
     * @email springnap@163.com
     *
     */
    public class LocalService extends Service {
    
        @Override
        public IBinder onBind(Intent intent) {
            return new LocalBinder();
        }   
            
        public void sayHelloWorld(){
            Toast.makeText(this.getApplicationContext(), "Hello World Local Service!", Toast.LENGTH_SHORT).show();
        }   
            
        public class LocalBinder extends Binder {
            LocalService getService() {
                // Return this instance of LocalService so clients can call public methods
                return LocalService.this;
            }   
        }   
    }

    local servcie 的代码如上,在onBinder方法中返回binder,binder包含了service的句柄,客户端得到句柄以后就可以调用servcie的公共方法了,这种调用方式是最常见的。

    客户端代码

    package com.ckt.wangxin;
    
    import android.app.Activity;
    import android.content.ComponentName;
    import android.content.Context;
    import android.content.Intent;
    import android.content.ServiceConnection;
    import android.os.Bundle;
    import android.os.IBinder;
    import android.util.Log;
    
    import com.ckt.wangxin.LocalService.LocalBinder;
    
    public class LocalServiceTestActivity extends Activity {
        static final String TAG = "LocalBinderTestActivity";
        ServiceConnection mSc;
        
        /** Called when the activity is first created. */
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
            
            mSc = new ServiceConnection(){
                @Override
                public void onServiceConnected(ComponentName name, IBinder service) {
                    Log.d(TAG, "service connected");
                    LocalService ss = ((LocalBinder)service).getService();
                    ss.sayHelloWorld();
                }
    
                @Override
                public void onServiceDisconnected(ComponentName name) {
                    Log.d(TAG, "service disconnected");
                }
            };
        }
        
        @Override
        protected void onStart() {
            super.onStart();
            Log.d(TAG, this.getApplicationContext().getPackageCodePath());
            Intent service = new Intent(this.getApplicationContext(),LocalService.class);
            this.bindService(service, mSc, Context.BIND_AUTO_CREATE);
        }
    
        @Override
        protected void onStop() {
            super.onStop();
            //must unbind the service otherwise the ServiceConnection will be leaked.
            <span style="color: rgb(255, 0, 0); ">this.unbindService(mSc);</span>
        }
    }

    需要注意的是在onStop中要解绑定service, 否则会造成内存泄露的问题。

    2. 我们再看一下与另外一个进程中的service进行通信的问题(跨进程通信!)。

    如何将servcie运行在另外一个进程呢?在manifest 里面配置个属性就行了。

    android:process=":remote" , 代表这个service运行在同一个应用程序的不同进程中。

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.ckt.wangxin"
        android:versionCode="1"
        android:versionName="1.0" >
    
        <uses-sdk android:minSdkVersion="15" />
    
        <application
            android:icon="@drawable/ic_launcher"
            android:label="@string/app_name" >
            <activity
                android:name=".LocalServiceTestActivity"
                android:label="@string/app_name" >
               <!--  <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter> -->
            </activity>
            <service android:name=".LocalService"></service>
            <!-- android:process=":remote" specify this service run in 
            another process in the same application. -->
            <service android:name=".RemoteService" android:process=":remote"></service>
            <activity android:name="RemoteServiceTestActivity">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
                
            </activity>
        </application>
    
    </manifest>

    客户端可以使用Messenger发送消息到service。

    客户端代码:

    package com.ckt.wangxin;
    
    import android.app.Activity;
    import android.content.ComponentName;
    import android.content.Context;
    import android.content.Intent;
    import android.content.ServiceConnection;
    import android.os.Bundle;
    import android.os.Handler;
    import android.os.IBinder;
    import android.os.Message;
    import android.os.Messenger;
    import android.os.RemoteException;
    import android.util.Log;
    import android.widget.Toast;
    
    public class RemoteServiceTestActivity extends Activity {
        static final String TAG = "RemoteServiceTestActivity";
        ServiceConnection mSc;
        public static final int SAY_HELLO_TO_CLIENT = 0;
        /**
         * Handler of incoming messages from service.
         */
        class IncomingHandler extends Handler {
            @Override
            public void handleMessage(Message msg) {
                switch (msg.what) {
                    case SAY_HELLO_TO_CLIENT:
                        Toast.makeText(RemoteServiceTestActivity.this.getApplicationContext(), "Hello World Remote Client!",
                                Toast.LENGTH_SHORT).show();
                        break;
                    default:
                        super.handleMessage(msg);
                }
            }
        }
        
        Messenger messenger_reciever = new Messenger(new IncomingHandler());
        
        /** Called when the activity is first created. */
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
            
            mSc = new ServiceConnection(){
                @Override
                public void onServiceConnected(ComponentName name, IBinder service) {
                    Log.d(TAG, "service connected");
                    <span style="color: rgb(204, 0, 0); ">Messenger messenger = new Messenger(service);
                    Message msg = new Message();
                    msg.what = RemoteService.MSG_SAY_HELLO;</span>
                    msg.replyTo = messenger_reciever;
                    try {
                        <span style="color: rgb(255, 0, 0); ">messenger.send(msg);</span>
                    } catch (RemoteException e) {
                        e.printStackTrace();
                    }
                }
    
                @Override
                public void onServiceDisconnected(ComponentName name) {
                    Log.d(TAG, "service disconnected");
                }
            };
        }
        
        @Override
        protected void onStart() {
            super.onStart();
            Log.d(TAG, this.getApplicationContext().getPackageCodePath());
            Intent service = new Intent(this.getApplicationContext(),RemoteService.class);
            this.bindService(service, mSc, Context.BIND_AUTO_CREATE);
        }
    
        @Override
        protected void onStop() {
            super.onStop();
            //must unbind the service otherwise the ServiceConnection will be leaked.
            this.unbindService(mSc);
        }
    }

    获得service端传来的binder,用来构建一个Messenger向service发送消息。

    service端代码:

    package com.ckt.wangxin;
    
    import android.app.Service;
    import android.content.Intent;
    import android.os.Handler;
    import android.os.IBinder;
    import android.os.Message;
    import android.os.Messenger;
    import android.os.RemoteException;
    import android.widget.Toast;
    
    public class RemoteService extends Service {
    
        public static final int MSG_SAY_HELLO = 0;
    
        @Override
        public IBinder onBind(Intent intent) {
          <span style="color: rgb(204, 0, 0); ">  return messager.getBinder();</span>
        }
    
        Handler IncomingHandler = new Handler() {
    
            @Override
            public void handleMessage(Message msg) {
                if(msg.replyTo != null){
                    Message msg_client = this.obtainMessage();
                    msg_client.what = RemoteServiceTestActivity.SAY_HELLO_TO_CLIENT;
                    try {
                        ((Messenger)msg.replyTo).send(msg_client);
                    } catch (RemoteException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
                switch (msg.what) {
                    case MSG_SAY_HELLO:
                        Toast.makeText(RemoteService.this.getApplicationContext(), "Hello World Remote Service!",
                                Toast.LENGTH_SHORT).show();
                        break;
                    default:
                super.handleMessage(msg);
                }
            }
    
        };
        
        Messenger  messager = new Messenger (IncomingHandler);
    }

    构建一个Messenger,包含一个handler,然后将messenger的binder传给客户端,客户端可以通过handler再构造一个messenger与service通信,消息在handler里面被处理。

    现在是service端单向响应客户端的消息,同理可以做成双向发送消息,实现双向通信。

    demo 源码可以在这里下载   源代码下载

  • 相关阅读:
    UVa 12174 (滑动窗口) Shuffle
    UVa 1607 (二分) Gates
    CodeForces ZeptoLab Code Rush 2015
    HDU 1525 (博弈) Euclid's Game
    HDU 2147 (博弈) kiki's game
    UVa 11093 Just Finish it up
    UVa 10954 (Huffman 优先队列) Add All
    CodeForces Round #298 Div.2
    UVa 12627 (递归 计数 找规律) Erratic Expansion
    UVa 714 (二分) Copying Books
  • 原文地址:https://www.cnblogs.com/zhujiabin/p/6029854.html
Copyright © 2011-2022 走看看