Android Studio实现远程服务

AndroidStudio实现远程服务

(1)  什么是远程服务

(2)  Android实现原理

(3)  实例讲解

 

一、什么是远程服务

简单来说就是:从一个进程调用另一个进程中的服务程序。

二、Android实现原理

       如图1所示:

Android Studio实现远程服务_第1张图片

图1 android远程服务示意图

(1)    客户端一般是自定义的Activity,通过bindService()发起服务绑定

(2)    服务端,通过onBind()响应绑定请求,并返回共接口的Binder

(3)    客户端将接收到的Binder转换成接口对象ISecondary,好比获得了远程对象通信接口的应用

(4)    由于客户端与服务端定义了相同的接口(AIDL文档相同),所以可以通过(3)中的ISecondary对象调用接口中的方法,如此一来访问远程服务的方法如同访问本地对象的方法一般

(5)    通过接口实现代码将请求传给服务对象

(6)    服务代码调用自己的方法

 

二、实例讲解

分别创建两个Android Application,ServiceClient和ServicServer

 

服务端:ServicServer

创建接口文件:IParams.aidl

import com.zdang.mservice.Pet;
import com.zdang.mservice.Person;
interface IParams {
  
List getPetByOwner(in Person owner);
}

 

该接口中包含了自定义的Object Person和Pet,所以必须为他们分别创建Person.aidl 和Pet.aidl,内容如下

Person.aidl

package com.zdang.mservice;
parcelable Person;

 

package com.zdang.mservice;
parcelable Pet;

如果不创建上面两个文件则编译时会报错:找不到定义的类

 

然后是自定义的Person.java和Pet.java

 

public class Person implements Parcelable{
    private int id;
    private String petName;

    public Person(){

    }
    public Person(int id, String name){
        super();
        this.id=id;
        this.petName=name;
    }

    protected Person(Parcel in) {
        this.id = in.readInt();
        this. petName = in.readString();
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getPetName() {
        return petName;
    }

    public void setPetName(String petName) {
        this.petName = petName;
    }


    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(id);
        dest.writeString(petName);
    }

    public static final Creator CREATOR = new Creator() {
        @Override
        public Person createFromParcel(Parcel in) {
            return new Person(in);
        }

        @Override
        public Person[] newArray(int size) {
            return new Person[size];
        }
    };

    @Override
    public boolean equals(Object obj) {

        if(this==obj){
            return true;
        }
        if(obj==null){
            return false;
        }

        if(getClass()!=obj.getClass()){
            return false;
        }

        Person other= (Person) obj;
        if(petName ==null){
            if(other.petName!=null) return false;
        }else if(!petName.equals(other.petName)) {
            return false;
        }
        return true;
    }

    @Override
    public int hashCode() {
        final int prime=31;
        int result=1;
        result=prime*result+((petName==null)?0: petName.hashCode());
        return result;
    }
}

 

Pet.java与Person.java类似,需要指出的是:自定义的类必须要实现串行化接口Parcelable否则不能够作为参数传递,该接口的实现可参照代码。

 

服务类:MyService

public class MyService extends Service{
    private static  Map,List> paramList=new HashMap,List>();
    private  static  List pet02;
    static {
        List pet01=new ArrayList();
        pet01.add(new Pet("duck","black"));
        pet01.add(new Pet("chicken","golden"));
        paramList.put(new Person(1,"tom"),pet01);

        pet02=new ArrayList();
        pet02.add(new Pet("pig","white"));
        pet02.add(new Pet("tiger","yellow"));
        paramList.put(new Person(2,"will"),pet02);
    }

    @Override
    public void onCreate() {
        super.onCreate();
    }

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

    IParams.Stub iParams=new IParams.Stub(){
        @Override
        public IBinder asBinder() {
            return null;
        }

        @Override
        public List getPetByOwner(Person owner) throws RemoteException {
            return paramList.get(owner);
        }
    };

    @Override
    public void onDestroy() {
        super.onDestroy();
    }
}

 

onBind()放回一个IParam.stub对象供客户端调用。

AndroidManifest.xml

android:name=".UsbService"
    android:process=":remote"
    android:exported="true">
    
        android:name="com.zdang.service.mservice"/>
    

Android:process=”:remote”声明该服务为远程服务

Android:name=”com.zdang.service.mservice”设置该服务的action

 

客户端:ServiceClient

 
 

private void startBinderService(){
    if(mService==null){
      Intent intent=new Intent();
      intent.setAction("com.zdang.service.usbservice");
      bindService(intent,serviceConnection,Context.BIND_AUTO_CREATE);
    }
 
private ServiceConnection serviceConnection=new ServiceConnection() {
    @Override
public void onServiceConnected(ComponentName name, IBinder service) {
        mService= IParams.Stub.asInterface(service);
        if(mService==null){
            Toast.makeText(getApplicationContext(),"mService is null!",Toast.LENGTH_LONG).show();
        }
    }

    @Override
    public void onServiceDisconnected(ComponentName name) {

    }
};

 

通过调用bindService(intent,serviceConnecttion,Context.BIND_AUTO_CREATE),与后台服务绑定,其中intent.setAction(“com.zdang.service.mservice”);必须与服务端设置action保持一致,否则找不到服务。

注意事项:

1)    AIDL文件写完后ReBuild工程会自动生成接口实现文件

2)    客户端与服务端的接口必须保持一致:包括内容、包名、所有依赖的自定义对象

3)aidl中自定义的参数对象一定要为其单独定义xxx.aidl 并写入parcelabel xxx。

4) 自定义的参数对象必须实现parcelabel接口

 

 

此外在Android studio上如果编译出错可在build.grade(module)的android节点下添加

sourceSets {
    main {
        manifest.srcFile 'src/main/AndroidManifest.xml'
        java.srcDirs = ['src/main/java', 'src/main/aidl']
        resources.srcDirs = ['src/main/java', 'src/main/aidl']
        aidl.srcDirs = ['src/main/aidl']
        res.srcDirs = ['src/main/res']
        assets.srcDirs = ['src/main/assets']
    }
}

 

 

 

 

注明:本文大部分内容摘自《疯狂android讲义》

你可能感兴趣的:(android应用)