Android 绑定服务 bindService[通俗易懂]

Android 绑定服务 bindService[通俗易懂]绑定服务是客户端–服务器接口中的服务器。组件(如activity)和服务进行绑定后,可以发送请求、接收响应、执行进程间通信(IPC)。不会无限期在后台运行。要提供服务绑定,必须实现onBind()回调方法,该方法返回的IBinder对象定义了客户端用来与服务进行交互的编程接口。客户端可以通过调用bindService()绑定到服务。调用时,必须提供ServiceConnection的实现,后者会…

大家好,又见面了,我是你们的朋友全栈君。

绑定服务是客户端–服务器接口中的服务器。组件(如activity)和服务进行绑定后,可以发送请求、接收响应、执行进程间通信(IPC)。不会无限期在后台运行。

要提供服务绑定,必须实现onBind()回调方法,该方法返回的IBinder对象定义了客户端用来与服务进行交互的编程接口。

客户端可以通过调用bindService()绑定到服务。调用时,必须提供ServiceConnection的实现,后者会监控与服务的连接,当Android系统创建客户端与服务之间的连接时,会对ServiceConnection回调onServiceConnected(),向客户端传递用来与服务通信的IBinder。当实现绑定服务的时候,最重要的环节是定义onBind()回调方法返回的接口。

创建绑定服务

必须提供IBinder,用以提供客户端与服务进行交互的接口。

@Override


public IBinder onBind(Intent arg0) {


return sBinder;

}

客户端绑定到服务步骤:

1.实现ServiceConnection,重写两个回调方法:onServiceConnected()—系统会调用该方法以传递服务的onBind()返回的IBinder;onServiceDisconnected()—Android系统会在与服务的连接以外中断(或者随着activity 的生命周期stop)时调用该方法,当客户端取消绑定的时候,不会回调该方法

2.调用bindService(),传递ServiceConnection

3.当系统调用onServiceConnected()的回调方法时,可以使用接口定义的方法开始调用服务

4.要断开与服务的连接,请调用unBindService()

如果应用在客户端与服务仍然绑定的状态下被销毁了,则销毁会导致客户端取消绑定。

扩展binder类:通过扩展Binder类并重onBind()返回它的一个实例创建接口,客户端收到Binder后可以利用它直接访问Binder实现中的,甚至service中可用的公共方法

public class LocalService extends Service {
    // Binder given to clients
    private final IBinder mBinder = new LocalBinder();
    // Random number generator
    private final Random mGenerator = new Random();

    /**
     * Class used for the client Binder.  Because we know this service always
     * runs in the same process as its clients, we don't need to deal with IPC.
     */
    public class LocalBinder extends Binder {
        LocalService getService() {
            // Return this instance of LocalService so clients can call public methods
            return LocalService.this;
        }
    }

    @Override
    public IBinder onBind(Intent intent) {
        return mBinder;
    }

    /** method for clients */
    public int getRandomNumber() {
      return mGenerator.nextInt(100);
    }
}

LocalBinder为客户端提供了getService方法,以检索LocalService的当前实例。这样客户端便可调用服务中的公用方法。如客户端可以调用服务中的getRandomNumber()方法。

public class BindingActivity extends Activity {
    LocalService mService;
    boolean mBound = false;

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

    @Override
    protected void onStart() {
        super.onStart();
        // Bind to LocalService
        Intent intent = new Intent(this, LocalService.class);
        bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
    }

    @Override
    protected void onStop() {
        super.onStop();
        // Unbind from the service
        if (mBound) {
            unbindService(mConnection);
            mBound = false;
        }
    }

    /** Called when a button is clicked (the button in the layout file attaches to
      * this method with the android:onClick attribute) */
    public void onButtonClick(View v) {
        if (mBound) {
            // Call a method from the LocalService.
            // However, if this call were something that might hang, then this request should
            // occur in a separate thread to avoid slowing down the activity performance.
            int num = mService.getRandomNumber();
            Toast.makeText(this, "number: " + num, Toast.LENGTH_SHORT).show();
        }
    }

    /** Defines callbacks for service binding, passed to bindService() */
    private ServiceConnection mConnection = new ServiceConnection() {

        @Override
        public void onServiceConnected(ComponentName className,
                IBinder service) {
            // We've bound to LocalService, cast the IBinder and get LocalService instance
            LocalBinder binder = (LocalBinder) service;
            mService = binder.getService();
            mBound = true;
        }

        @Override
        public void onServiceDisconnected(ComponentName arg0) {
            mBound = false;
        }
    };
}

上例说明客户端如何使用ServiceConnection的实现和onServiceConnected()的回调绑定到服务,点击按键,会调用服务中的公共方法getRandomNumber()。客户端应在适当的时机进行取消绑定,如例子中在onStop()的时候进行取消服务绑定。

使用Messenger:如果想让接口跨不同进程工作,可以使用Messenger为服务创建接口。服务可以这种方式定义对应于不同类型Message对象的handler。该Handler是Messenger的基础,后者可以与客户端分享一个IBinder,从而让客户端利用Message对象向服务发送命令。

public class MessengerService extends Service {
    /** Command to the service to display a message */
    static final int MSG_SAY_HELLO = 1;

    /**
     * Handler of incoming messages from clients.
     */
    class IncomingHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_SAY_HELLO:
                    Toast.makeText(getApplicationContext(), "hello!", Toast.LENGTH_SHORT).show();
                    break;
                default:
                    super.handleMessage(msg);
            }
        }
    }

    /**
     * Target we publish for clients to send messages to IncomingHandler.
     */
    final Messenger mMessenger = new Messenger(new IncomingHandler());

    /**
     * When binding to the service, we return an interface to our messenger
     * for sending messages to the service.
     */
    @Override
    public IBinder onBind(Intent intent) {
        Toast.makeText(getApplicationContext(), "binding", Toast.LENGTH_SHORT).show();
        return mMessenger.getBinder();
    }
}

服务就是在Handler的handleMessage()方法中接收传入的message,并根据what成员决定下一步操作。客户端只需要根据服务返回的IBinder创建一个Messenger,然后利用send发送一条消息:

public class ActivityMessenger extends Activity {
    /** Messenger for communicating with the service. */
    Messenger mService = null;

    /** Flag indicating whether we have called bind on the service. */
    boolean mBound;

    /**
     * Class for interacting with the main interface of the service.
     */
    private ServiceConnection mConnection = new ServiceConnection() {
        public void onServiceConnected(ComponentName className, IBinder service) {
            // This is called when the connection with the service has been
            // established, giving us the object we can use to
            // interact with the service.  We are communicating with the
            // service using a Messenger, so here we get a client-side
            // representation of that from the raw IBinder object.
            mService = new Messenger(service);
            mBound = true;
        }

        public void onServiceDisconnected(ComponentName className) {
            // This is called when the connection with the service has been
            // unexpectedly disconnected -- that is, its process crashed.
            mService = null;
            mBound = false;
        }
    };

    public void sayHello(View v) {
        if (!mBound) return;
        // Create and send a message to the service, using a supported 'what' value
        Message msg = Message.obtain(null, MessengerService.MSG_SAY_HELLO, 0, 0);
        try {
            mService.send(msg);
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }

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

    @Override
    protected void onStart() {
        super.onStart();
        // Bind to the service
        bindService(new Intent(this, MessengerService.class), mConnection,
            Context.BIND_AUTO_CREATE);
    }

    @Override
    protected void onStop() {
        super.onStop();
        // Unbind from the service
        if (mBound) {
            unbindService(mConnection);
            mBound = false;
        }
    }
}

使用AIDL:AIDL(Android接口定义语言)执行所有将对象分解成原语的工作,操作系统可以识别这些原语并将它们编组到各进程中以执行IPC。如果想让服务同时处理多个请求,可以直接使用AIDL,这种情况下服务必须具备多线程处理能力,并采用线程安全式设计。如果需要使用AIDL,必须创建一个定义编程接口的.aidl 文件。AndroidSDK工具利用该文件生成一个实现接口并处理IPC的抽象类,随后可在服务内对其进行扩展。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/132629.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • ioctl函数详解_lseek函数

    ioctl函数详解_lseek函数 我这里说的ioctl函数是在驱动程序里的,因为我不知道还有没有别的场合用到了ioctl,所以就规定了我们讨论的范围。为什么要写篇文章呢,是因为我前一阵子被ioctl给搞混了,这几天才弄明白它,于是在这里清理一下头脑。一、什么是ioctl。ioctl是设备驱动程序中对设备的I/O通道进行管理的函数。所谓对I/O通道进行管理,就

    2022年10月17日
  • 电容的分类及作用_热敏电阻的工作原理及作用

    电容的分类及作用_热敏电阻的工作原理及作用旁路旁路电容是为本地器件提供能量的储能器件,它能使稳压器的输出均匀化,降低负载需求。就像小型可充电电池一样,旁路电容能够被充电,并向器件进行放电。为尽量减少阻抗,旁路电容要尽量靠近负载器件的供电电源管脚和地管脚。这能够很好地防止输入值过大而导致的地电位抬高和噪声。地电位是地连接处在通过大电流毛刺时的电压降。去耦去耦,又称解耦。从电路来说,总是可以区分为驱动的源和被驱动的负载。如果

  • angular指令笔记(一):ng-options

    angular指令笔记(一):ng-options

  • usb转485驱动

    usb转485驱动usb转485驱动是官方提供的一款USB驱动,本站收集提供高速下载,用于解决USB接口不能正常识别,无法正常使用的问题,本动适用于:WindowsXP/Windows7/Windows8/Windows1032/64位操作系统。有需要的朋友可以来本站下载安装。usb转485驱动http://www.equdong.net/qtrj/usbdrv/16155.html…

  • 有return的情况下try catch finally的执行顺序(最有说服力的总结)

    有return的情况下try catch finally的执行顺序(最有说服力的总结)结论:1、不管有木有出现异常,finally块中代码都会执行;2、当try和catch中有return时,finally仍然会执行;3、finally是在return后面的表达式运算后执行的(此时并没有返回运算后的值,而是先把要返回的值保存起来,管finally中的代码怎么样,返回的值都不会改变,任然是之前保存的值),所以函数返回值是在finally执行前确定的;4、finally

  • plsql13连接oracle配置_plsql developer配置数据库连接

    plsql13连接oracle配置_plsql developer配置数据库连接由于硬件技术的不断更新,Win7系统逐渐成为主流,而且计算机内存逐渐增大,为了充分的利用内存资源(因为32为系统最多只能用到3G左右的内存),提高系统性能,很多人开始使用Win7(64Bit)的系统。在64位系统上安装64位的Oracle数据库,但是没有对应的64位PL/SQLDeveloper,此时就不能使用PL/SQLDeveloper来进行直接连接的,所以要想实现连接还得需要其他途径来完

    2022年10月12日

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号