AIDL跨进程的服务

AIDL跨进程的服务:

Android系统中的进程之间不能共享内存,因此,需要提供一些机制在不同进程之间进行数据通信。
为了使其他的应用程序也可以访问本应用程序提供的服务,Android系统采用了远程过程调用(Remote Procedure Call,RPC)方式来实现。与很多其他的基于RPC的解决方案一样,Android使用一种接口定义语言(Interface Definition Language,IDL)来公开服务的接口。我们知道4个Android应用程序组件中的3个(Activity、BroadcastReceiver 和ContentProvider)都可以进行跨进程访问,另外一个Android应用程序组件Service同样可以。因此,可以将这种可以跨进程访问的服务称为AIDL(Android Interface Definition Language)服务。
一,监听电话:
1.在main目录下,创建aidl目录
2.在aidl目录下,创建两个包,并复制两个文件到对应的包中,并Make Project
com.android.internal.telephony 对应的ITelephony.aidl
android.telephony 对应的NeighboringCellInfo.aidl
3.在MainActivity中,声明两个变量
 private TelephonyManager tm;
    private PhoneStateListener listener;
TelephonyManager 获取电话服务
PhoneStateListener 电话状态监听
4.在onCreate方法中,初始化变量
tm=(TelephonyManager) getSystemService(TELEPHONY_SERVICE);
        listener=new PhoneStateListener(){

            @Override
            public void onCallStateChanged(int state, String incomingNumber) {
                // TODO Auto-generated method stub
                super.onCallStateChanged(state, incomingNumber);
                switch (state) {
                    case TelephonyManager.CALL_STATE_IDLE:{
                        Log.i("info", "空闲状态");
                    }
                    break;

                    case TelephonyManager.CALL_STATE_OFFHOOK:{
                        Log.i("info", "占线状态");

                    }
                    break;
                    case TelephonyManager.CALL_STATE_RINGING:{
                        Log.i("info", "响铃状态");
                        Log.i("info", "来电:"+incomingNumber);
                        //拦截来电代码:
                        catComeCall();

                    }
                    break;
                }
            }

        };
        tm.listen(listener, PhoneStateListener.LISTEN_CALL_STATE);
5.写一个拦截电话的方法
 protected void catComeCall() {
        // 拦截来电
        try {
            Method method=Class.forName("android.os.ServiceManager")
                    .getMethod("getService", String.class);
            //获取远程TELEPHONY_SERVICE的IBinder对象的代理
            IBinder iBinder=(IBinder) method.invoke(null,new Object[]{TELEPHONY_SERVICE});
            //将IBinder对象的代理转换为ITelephony对象
            ITelephony telephony=ITelephony.Stub.asInterface(iBinder);
            //挂断电话
            telephony.endCall();

        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }
6.在Activity退出时,把监听设置为不监听
 @Override
    protected void onDestroy() {
        // TODO Auto-generated method stub
        super.onDestroy();
        tm.listen(listener, PhoneStateListener.LISTEN_NONE);
    }
7.权限声明
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <uses-permission android:name="android.permission.CALL_PHONE" />
    <uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />
PROCESS_OUTGOING_CALLS 允许应用程序监听、控制、取消呼出电话的权限
READ_PHONE_STATE 读取电话状态权限
二,服务端写法:
package com.qf.xs.day24servieraidl;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;

/**
 * Aidl实现进程间通信的步骤:
 * 服务端:
 * 1.定义aidl文件,在接口中声明服务可以提供给客户端使用的方法
 * 2.重构项目
 * 3.定义类继承Service,重写onBind方法
 *   3.1 定义一个内部类继承IXiaoHuangAidlInterface.Stub
 *   3.2 实例化Stub的子类
 *   3.3 在onBind方法中返回Stub的子类对象即可
 *
 * 4.注册到清单
 */
public class XiaoHuangService extends Service {
    public XiaoHuangService() {
    }

    public void sing(String name) {
        Log.e("print","小黄在唱歌:"+name);
    }

    //   Stub类的原型:  class Stub extends Binder implements IXiaoHuangAidlInterface
    public class XiaoHuangBinder extends IXiaoHuangAidlInterface.Stub {
        @Override
        public void sing(String name) throws RemoteException {
                XiaoHuangService.this.sing(name);
        }
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.e("print", "onCreate.....");
    }

    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        Log.e("print", "onBind.....");
        return new XiaoHuangBinder();
    }

    @Override
    public void onDestroy() {
        Log.e("print", "onDestroy.....");
        super.onDestroy();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.e("print", "onStartCommand.....");
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public boolean onUnbind(Intent intent) {
        Log.e("print", "onUnbind.....");
        return super.onUnbind(intent);
    }
}
1.在main目录下,创建aidl目录
// IXiaoHuangAidlInterface.aidl
package com.qf.xs.day24servieraidl;

// Declare any non-default types here with import statements
/**
* aidl声明的接口:
* 1.接口interface前不能加任何修饰符
* 2.接口中声明的方法不能有任何修饰符
* 3.接口中声明的方法的参数和返回值的类型是有要求的
*   支持的类型:
*   基本类型,String,
*
*
* aidl,修改后,必须重构项目,------开发工具就会自动将aidl声明的接口生成对应的java的接口
* */
interface IXiaoHuangAidlInterface {
   void sing(String name);
}
2.在aidl目录中,写一个声明接口声明,并放在对应的包名下
aidl声明的接口:
1》.接口interface前不能加任何修饰符
2》.接口中声明的方法不能有任何修饰符
3》.接口中声明的方法的参数和返回值的类型是有要求的
支持的类型:
基本类型,String,
3.定义类继承Service,重写onBind方法
package com.qf.xs.day24servieraidl;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;

/**
 * Aidl实现进程间通信的步骤:
 * 服务端:
 * 1.定义aidl文件,在接口中声明服务可以提供给客户端使用的方法
 * 2.重构项目
 * 3.定义类继承Service,重写onBind方法
 *   3.1 定义一个内部类继承IXiaoHuangAidlInterface.Stub
 *   3.2 实例化Stub的子类
 *   3.3 在onBind方法中返回Stub的子类对象即可
 *
 * 4.注册到清单
 */
public class XiaoHuangService extends Service {
    public XiaoHuangService() {
    }

    public void sing(String name) {
        Log.e("print","小黄在唱歌:"+name);
    }

    //   Stub类的原型:  class Stub extends Binder implements IXiaoHuangAidlInterface
    public class XiaoHuangBinder extends IXiaoHuangAidlInterface.Stub {
        @Override
        public void sing(String name) throws RemoteException {
                XiaoHuangService.this.sing(name);
        }
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.e("print", "onCreate.....");
    }

    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        Log.e("print", "onBind.....");
        return new XiaoHuangBinder();
    }

    @Override
    public void onDestroy() {
        Log.e("print", "onDestroy.....");
        super.onDestroy();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.e("print", "onStartCommand.....");
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public boolean onUnbind(Intent intent) {
        Log.e("print", "onUnbind.....");
        return super.onUnbind(intent);
    }
}
1》定义一个内部类继承IXiaoHuangAidlInterface.Stub
2》实例化Stub的子类
3》在onBind方法中返回Stub的子类对象即可
4.注册Service
 <service
            android:name=".XiaoHuangService"
            android:enabled="true"
            android:exported="true"><!--这里要为true 其他应用是否可以和它交互-->
            <intent-filter>
 				<!--这个是其他应用访问该服务的的身份标识-->
                <action android:name="com.xiaohuang.service"></action>
                <category android:name="android.intent.category.DEFAULT"></category>
            </intent-filter>
        </service>
重要:注册服务的时候,需要给服务添加一个动作(身份标识)。
三,访问端写法:
package com.qf.xs.day24aidldemo;

import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.os.RemoteException;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;

import com.qf.xs.day24servieraidl.IXiaoHuangAidlInterface;

/**
 * Aidl客户端
 * 1.创建aidl文件,必须和服务端aidl文件一模一样
 *   可以直接拷贝,拷贝到项目目录/main/
 *
 *  2.重构项目
 *
 * 3.定义类实现ServiceConnection接口,重写onServiceConnected方法,
 *   在这个方法中,利用Stub的asInterface方法将IBinder参数转换成接口对象
 *
 * 4.实例化ServiceConnection,通过调用bindService 绑定服务
 *
 * 5.服务连接成功,就通过接口调用服务中的方法即可
 */
public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    ServiceConnection connection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
//            IXiaoHuangAidlInterface asInterface(android.os.IBinder obj)
            iXiaoHuangAidlInterface = IXiaoHuangAidlInterface.Stub.asInterface(service);
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    };
    private IXiaoHuangAidlInterface iXiaoHuangAidlInterface;

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

    private void initView() {
        findViewById(R.id.start_btn).setOnClickListener(this);
        findViewById(R.id.stop_btn).setOnClickListener(this);
        findViewById(R.id.bind_btn).setOnClickListener(this);
        findViewById(R.id.unbind_btn).setOnClickListener(this);
        findViewById(R.id.invoke_btn).setOnClickListener(this);

    }

    @Override
    public void onClick(View v) {
        //3.0以后,服务的意图,必须是显式意图
//        Intent intent = new Intent("com.xiaohuang.service");
        Intent intent = new Intent();
        ComponentName comName= new ComponentName("com.qf.xs.day24servieraidl",//包名
                "com.qf.xs.day24servieraidl.XiaoHuangService");//类名
        intent.setComponent(comName);

        switch (v.getId()){
            case R.id.start_btn:
                startService(intent);
                break;
            case R.id.stop_btn:
                stopService(intent);
                break;
            case R.id.bind_btn:
                bindService(intent, connection,BIND_AUTO_CREATE);
                break;
            case R.id.invoke_btn:
                try {
                    iXiaoHuangAidlInterface.sing("冰雨");
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
                break;
            case R.id.unbind_btn:
                unbindService(connection);
                connection = null;
                break;
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (connection != null) {
            unbindService(connection);
            connection = null;
        }
    }
}
1》复制服务端的aidl目录到main目录下,并重构:Build--make Project.
2》定义类实现ServiceConnection接口,重写onServiceConnected方法,
在这个方法中,利用Stub的asInterface方法将IBinder参数转换成接口对象
ServiceConnection connection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
//            IXiaoHuangAidlInterface asInterface(android.os.IBinder obj)
            iXiaoHuangAidlInterface = IXiaoHuangAidlInterface.Stub.asInterface(service);
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    };
    private IXiaoHuangAidlInterface iXiaoHuangAidlInterface;

	        public void onServiceConnected(ComponentName name, IBinder service) {
//            IXiaoHuangAidlInterface asInterface(android.os.IBinder obj)
            iXiaoHuangAidlInterface = IXiaoHuangAidlInterface.Stub.asInterface(service);
        }
3》实例化ServiceConnection,通过调用bindService 绑定服务
 //3.0以后,服务的意图,必须是显式意图
//        Intent intent = new Intent("com.xiaohuang.service");
        Intent intent = new Intent();
        ComponentName comName= new ComponentName("com.qf.xs.day24servieraidl",//包名
                "com.qf.xs.day24servieraidl.XiaoHuangService");//类名
        intent.setComponent(comName);
 		bindService(intent, connection,BIND_AUTO_CREATE);
4》服务连接成功,就通过接口调用服务中的方法即可
 try {
                    iXiaoHuangAidlInterface.sing("冰雨");
                } catch (RemoteException e) {
                    e.printStackTrace();
                }













猜你喜欢

转载自blog.csdn.net/yang__k/article/details/80532683