今天在这里给大家介绍Android 四大组件中service中的绑定模式onBind(),Activity和Service 之间可以绑定然后做到数据的交互,比如我做一个登录然后在服务中去进行判断,在这里演示一个简单点的Demo就是一个普通的登录:


布局如下,二个EditText和一个登录的Button:

<EditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/main_qqname_edit"
        android:hint="请输入用户名/QQ/电话号码"/>
    <EditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/main_qqpwd_edit"
        android:hint="请输入密码"/>
    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="login"
        android:text="登录"/>

在MainActivity中拿到几个控件然后获取值,再进行与服务之间的绑定


private EditText main_qqname_edit;
    private EditText main_qqpwd_edit;
    private Intent intent;
    private QQLoginInterface qqLoginInterface;
    private QQLoginInterfaceOut qqLoginInterfaceOut;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //用户名的控件
        main_qqname_edit = (EditText) findViewById(R.id.main_qqname_edit);
        //密码的控件
        main_qqpwd_edit = (EditText) findViewById(R.id.main_qqpwd_edit);
        //绑定服务需要的Intent
        intent = new Intent(this,QQLoginServices.class);
    }
        //服务需要的ServiceConnection
        ServiceConnection connection=new ServiceConnection() {
        //绑定服务成功会调用的方法
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            qqLoginInterface = (QQLoginInterface) iBinder;

           // qqLoginInterfaceOut = QQLoginInterfaceOut.Stub.asInterface(iBinder);
        }
        //绑定服务失败会调用的方法
        @Override
        public void onServiceDisconnected(ComponentName componentName) {

        }
    };
        //进行交互时绑定服务
    @Override
    protected void onResume() {
        super.onResume();
        //绑定服务
        bindService(intent,connection, Service.BIND_AUTO_CREATE);
    }




具体的详解在注释中写清楚就不具体解释了,服务的类中内容如下,注释状态中的代码不予本次内容有关:

public class QQLoginServices extends Service {
//    class MyIBinder extends QQLoginInterfaceOut.Stub{
//
//        @Override
//        public boolean login(String qqname, String qqpwd) throws RemoteException {
//            if("100".equals(qqname)&&"123".equals(qqpwd)){
//                return true;
//            }
//            return false;
//        }
//    }

//onBind()方法中需要一个IBinder的返回类型值,所以我们在这里实例化一个IBinder的子类Binder然后继承一个接口来重写这个方法提高安全性
    class MyIBinder extends Binder implements QQLoginInterface{

        @Override
        public boolean login(String qqname, String qqpwd) {
            if("100".equals(qqname)&&"123".equals(qqpwd)){
                return true;
            }
            return false;
        }
    }

//绑定服务时需要的生命周期:绑定
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return new MyIBinder();
    }
}

在点击按钮的时候进行如下操作:


//点击按钮的方法
    public void login(View view){
        String qqname=main_qqname_edit.getText().toString();
        String pwd=main_qqpwd_edit.getText().toString();
        boolean flag=qqLoginInterface.login(qqname,pwd);
      //  boolean flag= false;
       // try {
        //    flag = qqLoginInterfaceOut.login(qqname,pwd);
       // } catch (RemoteException e) {
       //     e.printStackTrace();
       // }

        Toast.makeText(this,""+flag,Toast.LENGTH_LONG).show();


    }

这里的qqLoginInterface是我们之前绑定服务成功时里面的那个接口,然后拿到接口里面的登录方法把值给传回去,在清单文件中配置一下Service:


<service android:name=".QQLoginServices"
            android:exported="true"
            ></service>

那么这里的Service中的绑定就这样了,要注意我们的绑定中的交互会放回Binder中写入方法的放回类型,如要需要改动可以自己更改类型。





好了,现在说一下AIDL ,Android接口语言,就是进程与进程之间的通信,比如demo1和demo2都可以使用一个登录的方法,那么就可以在demo2中去调用demo1的登录方法,就是提供一个接口你去调用。那么这里的布局就如上 只是多做一个demo,然后什么都不需要做很多的改变。


先创建一个AIDL,在Android studio中右击可以new 一个AIDL 然后输入一个名字,会产生一个AIDL的文件,并且会产生一个相对应的java文件。

在AIDL文件中吧我们接口中的方法放进去也就是如下:


interface QQLoginInterfaceOut {
     boolean login(String qqname,String qqpwd);

}



在服务类中需要更改由我们的AIDL作为IBinder返回,代码如下:


class MyIBinder extends QQLoginInterfaceOut.Stub{

        @Override
        public boolean login(String qqname, String qqpwd) throws RemoteException {
            if("100".equals(qqname)&&"123".equals(qqpwd)){
                return true;
            }
            return false;
        }
    }

直接继承我们的AIDL类点出其中的Stub就可以,然后在MainActivity中不需要我们之前的那个接口来接收了,由我们的AIDL来接收,需要更改的代码如下:


//服务需要的ServiceConnection
        ServiceConnection connection=new ServiceConnection() {
        //绑定服务成功会调用的方法
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            //qqLoginInterface = (QQLoginInterface) iBinder;

            qqLoginInterfaceOut = QQLoginInterfaceOut.Stub.asInterface(iBinder);
        }
        //绑定服务失败会调用的方法
        @Override
        public void onServiceDisconnected(ComponentName componentName) {

        }
    };



在点击事件中直接用qqLoginInterfaceOut点出其中的方法就可以。第一个demo就是这样,和上面介绍的在这里看不出什么变化,但是在第二个demo中我们可以直接访问这里的服务传回来值在这里做判断了,


第二个demo中布局什么的和上面的demo一样,只说一下需要改变的地方,首先把demo1中由AIDL产生的接口类同包名和类名Copy到与MainActivity的包同级目录下,

MainActivity下的需要更改的代码如下:


@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        main_qqname_edit = (EditText) findViewById(R.id.main_qqname_edit);
        main_qqpwd_edit = (EditText) findViewById(R.id.main_qqpwd_edit);
        intent = new Intent();
        ComponentName componentName=new ComponentName("com.example.android_services_bind_aidl","com.example.android_services_bind_aidl.QQLoginServices");
        intent.setComponent(componentName);
    }
            ServiceConnection connection=new ServiceConnection() {

        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            //  qqLoginInterface = (QQLoginInterface) iBinder;

            qqLoginInterfaceOut = QQLoginInterfaceOut.Stub.asInterface(iBinder);
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {

        }
    };



重点是Intent跳转通过ComponentName来进行跳转到demo1,ComponentName第一个参数是包名,第二个是包名加类名。

然后就可以轻松访问到demo1中的那个服务了。


今天的分享就到这了,可能有些地方说的不清楚,但是在demo1中代码中的注释希望大家看下可能可以帮助到。