什么是远程服务?

远程服务(Remote Service)也被称之为独立进程,它不受其它进程影响,可以为其它应用程序提供调用的接口——实际上就是进程间通信IPC(Inter-Process Communication),Android提供了AIDL(Android Interface Definition Language,接口描述语言)工具来帮助进程间接口的建立。

在Android中,不同的应用属于不同的进程(Process),一个进程不能访问其他进程的存储(可以通过ContentProvider实现)。

   优点:1.远程服务有自己的独立进程,不会受到其它进程的影响;

              2.可以被其它进程复用,提供公共服务;

              3.具有很高的灵活性。

   缺点:相对普通服务,占用系统资源较多,使用AIDL进行IPC也相对麻烦。

1、首先我们来简单深入了解远程服务,在此我们新建一个demo,在它的布局文件中增加两个ExitText文本域,再增加一个Button按钮。代码如下:

         
2、新建一个类(LoginService.java)继承Service,重写它的onBind()方法;写一个类继承Binder,实现一个自定义接口,实现业务方法,在onBind()方法中返回该类对象。在代码如下:

public class LoginService extends Service{    @Nullable    @Override    public IBinder onBind(Intent intent) {        Log.i("test", "onBind: ");        //如果你需要绑定服务,就需要返回值,否则默认为null        return new MyIbinder();    }    class MyIbinder extends Binder implements LoginInterface{       @Override        public boolean login(String name, String pwd) {          if ("sunny".equals(name) && "123".equals(pwd)) {//判断用户名和密码:如果密码正确就登录成功,否则失败               return true;           }            return false;       }//        public boolean login(String name,String pwd){//            if ("sunny".equals(name)&&"123".equals(pwd)) {//判断用户名和密码:如果密码正确就登录成功,否则失败//                return true;//              }//            return false;//        }//    }}
在清单文件AndroidManifest.xml 中对LoginService.java中配置如下所示:

 

3、新建一个自定义接口(LoginInterface),定义方法和属性。在LoginService.java中写一个类实现这个接口(LoginInterface)。代码如下:

package com.example.administrator.android_servicemain;/** * Created by Administrator on 2017/2/12. */public interface LoginInterface {    public boolean login(String name,String pwd);}
4、 在客户端MainActivity.java中与LoginService.java这个类绑定,传递ServiceConnection用来接收onBind()方法返回的Ibinder,强转为接口类型,就可以调用这个方法。绑定服务中有三个参数:<1>、需要Intent对象。<2>、Connection是远程服务的对象,可以使用匿名内部类(ServiceConnection)的方式实现。<3>、对于绑定操作,一般用BIDN_AUTO_CREATE;这个服务会在你绑定时自动创建。代码如下:

public class MainActivity extends AppCompatActivity {    private EditText et_main_name;    private EditText et_main_password;    private Intent intent;    private LoginService.MyIbinder myibinder;    private LoginInterface loginInterface;    private LoginInterfaceOut loginInterfaceOut;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);//获取文本域的值        et_main_name = (EditText) findViewById(R.id.et_main_name);        et_main_password = (EditText) findViewById(R.id.et_main_password);        intent = new Intent(this,LoginService.class);//开始绑定服务    }    //实列化一个对象    ServiceConnection serviceConnection=new ServiceConnection() {        @Override//绑定成功        public void onServiceConnected(ComponentName name, IBinder ibinder) {           loginInterface = (LoginInterface) ibinder;//这个接口就是等于你服务中的ibinder,服务中的ininder的实现了LoginInterface 这个接口,所以可以直接替换。          // myibinder = (LoginService.MyIbinder) ibinder;            Log.i("test", "onServiceConnected: 绑定成功!");        }        @Override//绑定失败        public void onServiceDisconnected(ComponentName name) {            Log.i("test", "onServiceConnected: 绑定失败!");        }    };//绑定服务    @Override    protected void onResume() {        //Service.BIND_AUTO_CREATE:这个服务在你绑定的时自动创建        bindService(intent,serviceConnection, Service.BIND_AUTO_CREATE);        super.onResume();    }    //按钮的点击事件    public void login(View view){        //获取文本框的用户名和密码        String name=et_main_name.getText().toString();        String pwd=et_main_password.getText().toString();           boolean flag= loginInterface.login(name,pwd);     //   boolean flag= myibinder.login(name,pwd);        Toast.makeText(MainActivity.this, ""+ flag  , Toast.LENGTH_SHORT).show();//        if ("sunny".equals(name)&&"123".equals(pwd)) {//判断用户名和密码:如果密码正确就登录成功,否则失败//            Toast.makeText(MainActivity.this, "" + name + " " + pwd, Toast.LENGTH_SHORT).show();//        }else {//            Toast.makeText(MainActivity.this, "登录失败!用户名或密码输入错误~~", Toast.LENGTH_SHORT).show();      //  }    }}

5、使用AIDL(Android interface define language):Android接口定义语言。可以在Android设备上两个进程之间进行进程间通信(interpricess communication,IPC)。新建一个aidl文件,然后将demo编译,它会自动生成aidl相对应的接口的java类。代码如下:

// LoginInterfaceOut.aidlpackage com.example.administrator.android_servicemain;interface LoginInterfaceOut { boolean login(String name, String pwd);}

然后MainActivity.java和LoginService.java代码同上,只需要修改代码即可。(1)在LoginService.java写一个类,继承LoginInterfaceOut.Stub,并重写它的方法。代码如下:

//AIDL:Android interface define language-->安卓接口定义语言public class LoginService extends Service{    @Nullable    @Override    public IBinder onBind(Intent intent) {        Log.i("test", "onBind: ");        //如果你需要绑定服务,就需要返回值,否则默认为null        return new MyIbinder();    }    class MyIbinder extends LoginInterfaceOut.Stub{//写一个类继承LoginInterfaceOut这个接口        @Override        public boolean login(String name, String pwd) throws RemoteException {            if ("sunny".equals(name) && "123".equals(pwd)) {//判断用户名和密码:如果密码正确就登录成功,否则失败                return true;            }            return false;        }    }}
(2)MainActivity.java:( 1、在连接之后可以获取服务对象;(2、必须用asinterface方法得到LoginService对象。 代码如下:

  @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);//获取文本域的值        et_main_name = (EditText) findViewById(R.id.et_main_name);        et_main_password = (EditText) findViewById(R.id.et_main_password);        intent = new Intent(this,LoginService.class);//开始绑定服务    }    //实列化一个对象    ServiceConnection serviceConnection=new ServiceConnection() {        @Override//绑定成功        public void onServiceConnected(ComponentName name, IBinder ibinder) {            loginInterfaceOut = LoginInterfaceOut.Stub.asInterface(ibinder);             Log.i("test", "onServiceConnected: 绑定成功!");        }        @Override//绑定失败        public void onServiceDisconnected(ComponentName name) {            Log.i("test", "onServiceConnected: 绑定失败!");        }    };//绑定服务    @Override    protected void onResume() {        //Service.BIND_AUTO_CREATE:这个服务在你绑定的时自动创建        bindService(intent,serviceConnection, Service.BIND_AUTO_CREATE);        super.onResume();    }    //按钮的点击事件    public void login(View view){        //获取文本域的用户名和密码        String name=et_main_name.getText().toString();        String pwd=et_main_password.getText().toString();        boolean flag= false;        try {            flag = loginInterfaceOut.login(name,pwd);        } catch (RemoteException e) {            e.printStackTrace();        }        Toast.makeText(MainActivity.this, ""+ flag  , Toast.LENGTH_SHORT).show();    }}
6、 再新建一个demo,将你要通信的AIDL产生的(LoginInterfaceOut)java类复制到demo中。其中demo的布局文件与上述一样,这时我们需要在MianActivity主activity中写入ComponentName componentName=new ComponentName("与进程进行通讯的包名","与进程进行通讯的包名下的服务名");intent.setComponent(componentName);多进程间启动Services;Android 5.0 之后,启动其他应用程序的服务,不允许使用隐式。代码如下:

public class MainActivity extends AppCompatActivity {     private EditText et_main_name;     private EditText et_main_password;     private LoginInterfaceOut loginInterfaceOut;     private Intent intent;     @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);         //获取文本域的值         et_main_name = (EditText) findViewById(R.id.et_main_name);         et_main_password = (EditText) findViewById(R.id.et_main_password);         intent = new Intent();         ComponentName componentName=new ComponentName("com.example.administrator.android_servicemain","com.example.administrator.android_servicemain.LoginService");         intent.setComponent(componentName);    }     ServiceConnection serviceConnection=new ServiceConnection() {         @Override         public void onServiceConnected(ComponentName name, IBinder ibinder) {             loginInterfaceOut = LoginInterfaceOut.Stub.asInterface(ibinder);             Log.i("test", "onServiceConnected: 绑定成功!");         }         @Override         public void onServiceDisconnected(ComponentName name) {             Log.i("test", "onServiceConnected: 绑定失败!");         }     };     //绑定服务     @Override     protected void onResume() {         //Service.BIND_AUTO_CREATE:这个服务在你绑定的时自动创建         bindService(intent,serviceConnection, Service.BIND_AUTO_CREATE);         super.onResume();     }     //按钮的点击事件     public void login(View view){         //获取文本框的用户名和密码         String name=et_main_name.getText().toString();         String pwd=et_main_password.getText().toString();         boolean flag= false;         try {             flag = loginInterfaceOut.login(name,pwd);         } catch (RemoteException e) {             e.printStackTrace();         }         Toast.makeText(MainActivity.this, ""+ flag  , Toast.LENGTH_SHORT).show();     }}
7、总结:
<1、远程服务(绑定服务):所谓远程指的是跨进程,而不是距离的远近。

<2、生命周期:多个组件可以绑定同一个远程服务,当所有的组件与远程服务解除绑定的时,远程服务也就会被销毁。

<3、AIDL(Android interface define language):Android接口定义语言。可以进行进程间的通信。

<4、LoginInterfaceOut.Stub是根据LoginInterfaceOut.aidl文件自动生成的,一般不需要去了解这个类的内容,只需写一个类继承LoginInterfaceOut.Stub即可。

<5、onBinder()方法必须返回LoginInterfaceOut.Stub类的子类,否则客户端无法获取服务对象。

更多相关文章

  1. Android应用程序请求SurfaceFlinger服务渲染Surface的过程分析
  2. Android下Bonjour服务的使用
  3. Android(安卓)应用程序进程启动过程源码分析
  4. Tabhost中Activity绑定Service
  5. 【android】欢迎来到Android多进程时代
  6. Android的IPC机制Binder的各个部分
  7. Android启动过程深入解析
  8. Android(安卓)启动过程详解
  9. Android(安卓)官方示例:android-architecture 学习笔记(四)之todo

随机推荐

  1. android hessian
  2. Android短彩信源码解析-短信发送流程(二)
  3. Android自定义Dialog(自定义主题、自定义
  4. Android(安卓)自绘输入框
  5. 仿QQ android 实战(学习 android 先来个QQ
  6. 2011.06.20——— android listview的拖
  7. Android中自定义对话框小结
  8. 简单总结RectF、Rect 和Matrix ,还有Pain
  9. android 执行shell命令代码
  10. android 开发中常用颜色,以及一些颜色的代