您的位置:首页 > 移动开发 > Android开发

Android基本功:跨进程调用Services(AIDL Service)

2016-08-15 18:34 441 查看
一、AIDL Service简介  

Android系统中,各个应用都运行在自己的进程中,进程之间一般无法直接进行通信,为了实现进程通信(interprocess communication,简称IPC),Android提供了AIDL Service;  

  

二、与本地Service不同 

本地Service:直接把IBinder对象本身传递给客户端的ServiceConnection的onServiceConnected方法的第二个参数; 

远程Service:只将IBinder对象的代理传给客户端的ServiceConnection的onServiceConnected方法的第二个参数; 

 

三、AIDL文件  

Android需要AIDL(Android Interface
Definition Language)来定义远程接口,这种接口定义语言并不是一种真正的变成语言,只是定义两个进程之间的通信接口; 

 

与Java接口相似,但是存在如下几点差异:  

AIDL定义接口的源代码必须以.aidl结尾;  

AIDL用到的数据类型,除了基本类型、String、List、Map、CharSequence之外,其它类型全部都需要导包,即使它们在同一个包中也需要导包; 

 

四、使用AIDL的步骤(详细代码可见AIDLService和AIDLClient项目) 

1.创建AIDL文件 

[java] view
plain copy

 





package com.example.aidlservice;   

   

interface ICat {   

    String getColor();   

    double getWeight();   

}   

定义好AIDL文件后,ADT工具会自动在gen/com/example/aidlservice/目录下生成一个ICat.java接口,该类内部包含一个Stub内部类,实现了IBinder,ICat两个接口,这个Stub类会作为远程Service回调类; 

 

2.将接口暴露给客户端 

[java] view
plain copy

 





package com.example.aidlservice;   

import java.util.Timer;   

import java.util.TimerTask;   

import com.example.aidlservice.ICat.Stub;   

import android.app.Service;   

import android.content.Intent;   

import android.os.IBinder;   

import android.os.RemoteException;   

   

public class AidlService extends Service {   

    String[] colors = new String[] { "红色", "黄色", "黑色" };   

    double[] weights = new double[] { 2.3, 3.1, 1.58 };   

    private String color;   

    private double weight;   

    private CatBinder catBinder;   

    Timer timer = new Timer();   

   

    @Override   

    public void onCreate() {   

        super.onCreate();   

        catBinder = new CatBinder();   

        timer.schedule(new TimerTask() {   

   

            @Override      

            public void run() {   

                // 随机地改变service组件内的color,weight属性的值   

                int rand = (int) (Math.random() * 3);     

                color = colors[rand];   

                weight = weights[rand];   

                System.out.println("---------" + rand);   

            }   

        }, 0, 800)};   

   

    @Override   

    public IBinder onBind(Intent arg0) {   

        /**    

        * 返回CatBinder对象,在绑定本地Service情况下,  

        * 该catBinder会直接传给客户端的ServiceConnected对象的ServiceConnected  

        * ()方法的第二个参数;在绑定远程Service的情况下   

        * ,只将catBinder对象的代理传给客户端的ServiceConnected对象的ServiceConnected()方法的第二个参数  

        */   

        return catBinder;   

    }   

   

    @Override   

    public void onDestroy() {   

        timer.cancel();   

    }   

   

    /**     

    * 继承Stub,也就是实现了ICat接口,并实现了IBinder接口  

    *   

    * @author pengcx  

    *  

    */   

    public class CatBinder extends Stub {   

        @Override   

        public String getColor() throws RemoteException {   

            return color;   

        }   

   

    @Override   

        public double getWeight() throws RemoteException {   

            return weight;   

        }   

    }   

}   

在AndroidManifext.xml文件中配置该Service;

[html] view
plain copy

 





<service android:name="com.example.aidlservice.AidlService" >   

    <intent-filter>   

        <action android:name="org.crazyit.aidl.action.AIDL_SERVICE" />   

    </intent-filter>   

 </service>   

 

3.客户端访问AIDLService 

将Service端的AIDL文件复制到客户端中,注意要在相同的包名下。 

 

[java] view
plain copy

 





package com.example.aidlclient;   

   

import com.example.aidlservice.ICat;   

import android.os.Bundle;   

import android.os.IBinder;   

import android.os.RemoteException;   

import android.view.View;   

import android.view.View.OnClickListener;   

import android.widget.Button;   

import android.widget.EditText;   

import android.app.Activity;   

import android.app.Service;   

import android.content.ComponentName;   

import android.content.Intent;   

import android.content.ServiceConnection;   

   

public class AidlClient extends Activity {   

    private ICat catService;   

    private Button getButton;   

    private EditText colorEditText, weightEditText;   

   

    private ServiceConnection conn = new ServiceConnection() {   

        @Override   

        public void onServiceDisconnected(ComponentName name) {   

            catService = null;   

        }   

   

        @Override   

        public void onServiceConnected(ComponentName name, IBinder service) {   

            // 获取远程Service的onBinder方法返回的对象代理   

            catService = ICat.Stub.asInterface(service);   

        }   

    };   

   

    @Override   

    protected void onCreate(Bundle savedInstanceState) {   

        super.onCreate(savedInstanceState);   

        setContentView(R.layout.activity_aidl_client);   

   

        getButton = (Button) findViewById(R.id.getbutton);   

        colorEditText = (EditText) findViewById(R.id.coloredittext);   

        weightEditText = (EditText) findViewById(R.id.weightedittext);   

   

        // 创建所需要绑定的Service的Intent   

        Intent intent = new Intent();   

        intent.setAction("org.crazyit.aidl.action.AIDL_SERVICE");   

        // 绑定远程的服务   

        bindService(intent, conn, Service.BIND_AUTO_CREATE);   

               

        getButton.setOnClickListener(new OnClickListener() {   

@Override   

public void onClick(View v) {   

    // 获取并显示远程service的状态   

    try {   

        colorEditText.setText(catService.getColor());   

        weightEditText.setText(catService.getWeight() + "");   

    } catch (RemoteException e) {   

        e.printStackTrace();   

    }   

}   

       });   

    }   

   

    @Override   

    protected void onDestroy() {   

        super.onDestroy();   

        // 解除绑定   

        this.unbindService(conn);   

    }   

}   



 

错误:java.lang.SecurityException:
Binder invocation to an incorrect interface。在使用上请注意,服务端与客户端都要有相同的接口(使用到的),这里的“相同”是指完全相同,包括包名,也就是说要在不同工程下建立相同的包名。 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: